2011-10-14 64 views
1

我創建了一個動態的dll來存放從我的數據庫創建的自定義對象。我可以按照我想要的方式創建該字段,但是我不知道如何調用構造函數。對於最終生成的結果,我想:C#反射:如何初始化在TypeBuilder中動態創建的字段?

public class Countries 
{ 
    public Countries() { } 
    public static readonly ReferenceObject USA = new ReferenceObject(120); 
    public static readonly ReferenceObject CAN = new ReferenceObject(13); 
    public static readonly ReferenceObject MEX = new ReferenceObject(65); 
    ... //These would be populated from the database 
} 

什麼,我得到的是

public class Countries 
{ 
    public Countries() { } 
    public static readonly ReferenceObject USA; 
    public static readonly ReferenceObject CAN; 
    public static readonly ReferenceObject MEX; 
    ... 
} 

如何設置的值,以新的初始化的對象?

AppDomain domain = AppDomain.CurrentDomain; 

AssemblyName aName = new AssemblyName("DynamicEnums"); 
AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save); 

ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); 

foreach(ReferenceType rt in GetTypes()) 
{ 
    TypeBuilder tb = mb.DefineType(rt.Name, TypeAttributes.Public); 

    foreach (Reference r in GetReferences(rt.ID)) 
    { 
     string name = NameFix(r.Name); 

     FieldBuilder fb = tb.DefineField(name, typeof(ReferenceObject), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal); 

     //Call constructor here... how??? 
    } 

    types.Add(tb.CreateType()); 
} 

ab.Save(aName.Name + ".dll"); 
+0

也許我想將它們轉換到DefineMethod或DefineProperty這裏...但最終的結果是,我想(「120」== Countries.USA)爲true,以及(Countries.USA == 120)在我的代碼中引用時爲true。 – Ehryk

+0

ReferenceObject基本上是一個int類型的包裝器,它可以將它與int或字符串進行比較。 – Ehryk

回答

4

位從我answer一份意大利麪到其他(非常類似)的問題,而是:

AppDomain domain = AppDomain.CurrentDomain; 

AssemblyName aName = new AssemblyName("DynamicEnums"); 
AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save); 

ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); 

// Store a handle to the ReferenceObject(int32 pValue) 
// constructor. 
ConstructorInfo referenceObjectConstructor = typeof(ReferenceObject).GetConstructor(new[] { typeof(int) }); 

foreach (ReferenceType rt in GetTypes()) 
{ 
    TypeBuilder tb = mb.DefineType(rt.Name, TypeAttributes.Public); 

    // Define a static constructor to populate the ReferenceObject 
    // fields. 
    ConstructorBuilder staticConstructorBuilder = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); 
    ILGenerator staticConstructorILGenerator = staticConstructorBuilder.GetILGenerator(); 

    foreach (Reference r in GetReferences(rt.ID)) 
    { 
     string name = r.Abbreviation.Trim(); 

     // Create a public, static, readonly field to store the 
     // named ReferenceObject. 
     FieldBuilder referenceObjectField = tb.DefineField(name, typeof(ReferenceObject), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.InitOnly); 

     // Add code to the static constructor to populate the 
     // ReferenceObject field: 

     // Load the ReferenceObject's ID value onto the stack as a 
     // literal 4-byte integer (Int32). 
     staticConstructorILGenerator.Emit(OpCodes.Ldc_I4, r.ID); 

     // Create a reference to a new ReferenceObject on the stack 
     // by calling the ReferenceObject(int32 pValue) reference 
     // we created earlier. 
     staticConstructorILGenerator.Emit(OpCodes.Newobj, referenceObjectConstructor); 

     // Store the ReferenceObject reference to the static 
     // ReferenceObject field. 
     staticConstructorILGenerator.Emit(OpCodes.Stsfld, referenceObjectField); 
    } 

    // Finish the static constructor. 
    staticConstructorILGenerator.Emit(OpCodes.Ret); 

    tb.CreateType(); 
} 

ab.Save(aName.Name + ".dll"); 
1

當一個寫在那裏字段在你的榜樣初始化像一個C#類,什麼的編譯器是產生在構造函數初始化代碼。

這是我認爲你應該做的:使用TypeBuilder.DefineConstructor來生成構造函數,並在裏面創建代碼來設置字段。