2013-05-21 57 views
2

我動態創建一個C#結構通過反射,當我檢查結構的類型,我調試我注意到StructLayoutAttribute.Pack被默認爲8。我想給包基本上設置爲1C#如何通過反射設置StructLayoutAttribute.Pack?

,我會喜歡通過反射通過增加該屬性的結構的聲明做什麼可以做:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 

我一直在使用反射創建類型後嘗試過,但由於StructLayoutAttribute屬性沒有二傳手,它拋出一個例外。

我的預感是它需要在ModuleBuilder.DefineType(我正在設置LayoutKind等)的調用中發生,但我沒有看到任何明顯的對應的TypeAttribute

任何指針讚賞。對於這裏的類完整代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.Reflection.Emit; 

namespace AcmeCo.Serializable 
{ 
    public class DynamicSimStructBuilder 
    { 

     private static Type structType; 

     public static object GetStructInstance() { 
      object ptInstance = Activator.CreateInstance(GetStruct(), new object[] { }); 
      return ptInstance; 
     } 

     public static Type GetStruct() { 

      if (structType != null) { 
       return structType; 
      } 

      AppDomain myDomain = AppDomain.CurrentDomain; 
      AssemblyName myAsmName = new AssemblyName("MyDynamicAssembly"); 

      AssemblyBuilder myAsmBuilder = 
       myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave); 

      ModuleBuilder structModule = myAsmBuilder.DefineDynamicModule("StructModule", "MyDynamicAssembly.dll"); 

      TypeBuilder structTypeBld = structModule.DefineType("AcmeCo.ThirdPartyAPIWrapper.DyanmicStruct", TypeAttributes.Public | 
       TypeAttributes.Sealed | TypeAttributes.SequentialLayout | 
       TypeAttributes.Serializable | TypeAttributes.AnsiClass, typeof(ValueType)); 

      // use a set of variables defined in an XML file to create Fields on the struct 
      ThirdPartyAPIVariableCollection collection = ThirdPartyAPIVariableCollection.Deserialize(); 
      foreach (ThirdPartyAPIVariable variable in collection.ThirdPartyAPIVariables) 
      { 
       FieldBuilder field = structTypeBld.DefineField(variable.Name, Type.GetType(variable.SystemDataType, true) , FieldAttributes.Public); 
      } 

      // Base class and base class constructor. 
      Type objType = Type.GetType("System.Object"); 
      ConstructorInfo objCtor = objType.GetConstructor(new Type[] { }); 

      Type[] ctorParams = { }; 

      ConstructorBuilder pointCtor = 
       structTypeBld.DefineConstructor(MethodAttributes.Public, 
               CallingConventions.Standard, ctorParams); 
      ILGenerator ctorIL = pointCtor.GetILGenerator(); 

      // Build the constructor. Begin by invoking the base class 
      // constructor. The zero-index parameter of the constructor 
      // is the new instance. Store the values of the fields. 
      ctorIL.Emit(OpCodes.Ldarg_0); 
      ctorIL.Emit(OpCodes.Call, objCtor); 
      ctorIL.Emit(OpCodes.Ret); 


      // Create the type, and then create an instance of the type 
      // (or not, doesn't hurt to comment the CreateInstance line out...) 
      Type ptType = structTypeBld.CreateType(); 

      object ptInstance = Activator.CreateInstance(ptType, new object[] { }); 

      DynamicSimStructBuilder.structType = ptType; 
      int sizeOfNewData = System.Runtime.InteropServices.Marshal.SizeOf(ptType); 
      Console.WriteLine("New type is: " + sizeOfNewData); 

      // save the newly created type to a DLL for use later 
      // (or not, doesn't hurt to comment the next line out...) 
      myAsmBuilder.Save("MyDynamicAssembly.dll"); 

      return ptType; 
     } 
    } 
} 

回答