Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用基类和其他字段从TypeBuilder创建动态类型会生成异常_C#_Inheritance_Reflection_Reflection.emit_Typebuilder - Fatal编程技术网

C# 使用基类和其他字段从TypeBuilder创建动态类型会生成异常

C# 使用基类和其他字段从TypeBuilder创建动态类型会生成异常,c#,inheritance,reflection,reflection.emit,typebuilder,C#,Inheritance,Reflection,Reflection.emit,Typebuilder,我试图基于只包含公共字段的现有类型创建一个动态类型。新的动态类型还必须继承另一个只具有完全实现的方法的基类型 我创建TypeBuilder指定基本类型,然后向其中添加公共字段,最后调用CreateType()。产生的错误消息是: 无法从程序集“MyDynamicsSembly”加载类型“InternalType”, Version=0.0.0.0,Culture=neutral,PublicKeyToken=null'因为字段 “first”没有给出明确的偏移量。” 对我来说,这意味着Creat

我试图基于只包含公共字段的现有类型创建一个动态类型。新的动态类型还必须继承另一个只具有完全实现的方法的基类型

我创建
TypeBuilder
指定基本类型,然后向其中添加公共字段,最后调用
CreateType()
。产生的错误消息是:

无法从程序集“MyDynamicsSembly”加载类型“InternalType”, Version=0.0.0.0,Culture=neutral,PublicKeyToken=null'因为字段 “first”没有给出明确的偏移量。”

对我来说,这意味着
CreateType
方法正在基类中查找公共字段“first”,这是一个问题,因为它不在基类中。为什么它认为添加的字段应该在基类中?还是我误解了例外

代码如下:

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);

为什么需要
ExplicitLayout
呢?请注意,第三方库使用非托管代码与可编程逻辑控制器(PLC)进行接口时需要它。我没有特别要求,可能是SequentialLayout就足够了。
CreateType
为我抛出了一个错误:mscorlib.dll中的System.TypeLoadException。它说我的类型有一个无效的格式,为什么?vulkanino,只是一个建议,但你应该尝试开始一个新的步伐。大多数人不阅读已经标记为“已回答”的线程。祝您好运。@dtaylor,也许您应该使用
TypeBuilder.SetParent(Type)
来告诉新继承的类它是继承的。您能演示一下如何使用该方法来动态(..)吗?谢谢您提供了这个非常好的主题。但是你不是在用基类复制一个新类,而不是继承基类吗?