gpt4 book ai didi

c# - 使用基类和附加字段从 TypeBuilder 创建动态类型会生成异常

转载 作者:太空狗 更新时间:2023-10-29 18:29:15 24 4
gpt4 key购买 nike

我正在尝试基于仅包含公共(public)字段的现有类型创建动态类型。新的动态类型还必须继承自仅具有完全实现方法的不同基类型。

我创建了指定基类型的 TypeBuilder,然后我将公共(public)字段添加到它,最后我调用了 CreateType()。产生的错误消息是:

"Could not load type 'InternalType' from assembly 'MyDynamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because field 'first' was not given an explicit offset."

对我来说,这意味着 CreateType 方法正在寻找基类中“first”的公共(public)字段,这是一个问题,因为它不存在。为什么它认为添加的字段应该在基类中?或者,我是否误解了异常?

代码如下:

public class sourceClass
{
public Int32 first = 1;
public Int32 second = 2;
public Int32 third = 3;
}

public static class MyConvert
{
public static object ToDynamic(object sourceObject, out Type outType)
{
// get the public fields from the source object
FieldInfo[] sourceFields = sourceObject.GetType().GetFields();

// get a dynamic TypeBuilder and inherit from the base type
AssemblyName assemblyName
= new AssemblyName("MyDynamicAssembly");
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder
= assemblyBuilder.DefineDynamicModule("MyDynamicModule");
TypeBuilder typeBuilder
= moduleBuilder.DefineType(
"InternalType",
TypeAttributes.Public
| TypeAttributes.Class
| TypeAttributes.AutoClass
| TypeAttributes.AnsiClass
| TypeAttributes.ExplicitLayout,
typeof(SomeOtherNamespace.MyBase));

// add public fields to match the source object
foreach (FieldInfo sourceField in sourceFields)
{
FieldBuilder fieldBuilder
= typeBuilder.DefineField(
sourceField.Name,
sourceField.FieldType,
FieldAttributes.Public);
}

// THIS IS WHERE THE EXCEPTION OCCURS
// create the dynamic class
Type dynamicType = typeBuilder.CreateType();

// create an instance of the class
object destObject = Activator.CreateInstance(dynamicType);

// copy the values of the public fields of the
// source object to the dynamic object
foreach (FieldInfo sourceField in sourceFields)
{
FieldInfo destField
= destObject.GetType().GetField(sourceField.Name);
destField.SetValue(
destObject,
sourceField.GetValue(sourceField));
}

// give the new class to the caller for casting purposes
outType = dynamicType;

// return the new object
return destObject;
}

最佳答案

好的,我在发帖后不久就想通了。我确实误读了错误消息。事实上,它与继承的基类无关。

当我创建类型时,我指定了必需的属性“TypeAttributes.ExplicitLayout”。不幸的是,我没有意识到在创建每个字段时我还必须为每个字段添加一个偏移量。异常消息是完全准确的。抱歉误报。更正后的代码如下:

public class SourceClass
{
public Int32 first = 1;
public Int32 second = 2;
public Int32 third = 3;
}

public static class MyConvert
{
public static object ToDynamic(object sourceObject, out Type outType)
{
Int32 fieldOffset = 0;

// get the public fields from the source object
FieldInfo[] sourceFields = sourceObject.GetType().GetFields();

// get a dynamic TypeBuilder and inherit from the base type
AssemblyName assemblyName
= new AssemblyName("MyDynamicAssembly");
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder
= assemblyBuilder.DefineDynamicModule("MyDynamicModule");
TypeBuilder typeBuilder
= moduleBuilder.DefineType(
"InternalType",
TypeAttributes.Public
| TypeAttributes.Class
| TypeAttributes.AutoClass
| TypeAttributes.AnsiClass
| TypeAttributes.ExplicitLayout,
typeof(SomeOtherNamespace.MyBase));

// add public fields to match the source object
foreach (FieldInfo sourceField in sourceFields)
{
FieldBuilder fieldBuilder
= typeBuilder.DefineField(
sourceField.Name,
sourceField.FieldType,
FieldAttributes.Public);
fieldBuilder.SetOffset(fieldOffset);
fieldOffset++;
}

// create the dynamic class
Type dynamicType = typeBuilder.CreateType();

// create an instance of the class
object destObject = Activator.CreateInstance(dynamicType);

// copy the values of the public fields of the
// source object to the dynamic object
foreach (FieldInfo sourceField in sourceFields)
{
FieldInfo destField
= destObject.GetType().GetField(sourceField.Name);
destField.SetValue(
destObject,
sourceField.GetValue(sourceObject));
}

// give the new class to the caller for casting purposes
outType = dynamicType;

// return the new object
return destObject;
}

编辑:上面的代码将不起作用。字段索引以字节为单位,因此当您增加偏移量时,您应该按照字段的大小这样做​​:

fieldOffset += sizeof(Int32);

关于c# - 使用基类和附加字段从 TypeBuilder 创建动态类型会生成异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18467235/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com