2013-08-27 32 views
6

Tôi đang cố gắng tạo loại động dựa trên loại hiện có chỉ chứa các trường công khai. Kiểu động mới cũng phải kế thừa từ một kiểu cơ sở khác mà chỉ có một phương thức được thực hiện đầy đủ.Tạo kiểu động từ TypeBuilder với một lớp cơ sở và các trường bổ sung tạo ra một ngoại lệ

Tôi tạo TypeBuilder chỉ định loại cơ sở, sau đó tôi thêm các trường công khai vào nó và cuối cùng tôi gọi CreateType(). kết quả được thông báo lỗi là:

"Không thể nạp kiểu 'InternalType' từ lắp ráp 'MyDynamicAssembly, Version = 0.0.0.0, Culture = trung tính, PublicKeyToken = null' vì lĩnh vực 'đầu tiên' không được trao một bù đắp rõ ràng. "

Với tôi điều này ngụ ý rằng phương pháp CreateType đang tìm kiếm trường công khai "đầu tiên" trong lớp cơ sở, đó là vấn đề bởi vì nó không có ở đó. Tại sao nó cho rằng trường được thêm vào phải nằm trong lớp cơ sở? Hoặc, tôi có hiểu lầm ngoại lệ không?

Đây là mã:

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

Trả lời

8

Ok, tôi figured này ra khoảnh khắc sau khi đăng. Tôi đã thực sự hiểu sai thông báo lỗi. Nó, trên thực tế, không có gì để làm với lớp cơ sở kế thừa.

Khi tôi tạo loại tôi đã chỉ định thuộc tính "TypeAttributes.ExplicitLayout" là bắt buộc. Thật không may, tôi đã không nhận ra rằng tôi cũng phải thêm một bù đắp cho từng lĩnh vực khi tôi tạo ra chúng. Thông báo ngoại lệ hoàn toàn chính xác. Xin lỗi cho các báo động giả. Mã được chỉnh sửa theo sau:

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

EDIT: Mã trên sẽ không hoạt động. Chỉ số trường bằng byte, do đó khi bạn tăng số dư, bạn nên làm như vậy theo kích thước của trường như sau:

fieldOffset += sizeof(Int32); 
+1

Tại sao 'ExplicitLayout' được yêu cầu? – svick

+0

svick, thư viện bên thứ ba yêu cầu sử dụng mã không được quản lý để giao tiếp với bộ điều khiển logic khả trình (PLC). Tôi không hỏi cụ thể, có thể là SequentialLayout sẽ đủ. – dtaylor

+0

'CreateType' ném một lỗi cho tôi: 'System.TypeLoadException' trong mscorlib.dll. Nó nói loại của tôi có một định dạng không hợp lệ, tại sao? – vulkanino

Các vấn đề liên quan