2015-05-20 1 views
0

(Мой код несколько беспорядок C# и VB.NET) Я пытаюсь Выделяю класс, который выглядит следующим образом:Как исправить код, чтобы назначить значение/ссылку на статическое поле класса, вызвав его конструктор?

public class SWTTFields 
{ 
    private string fieldName; 
    private int startPosition; 
    private int endPosition; 

    public static readonly SWTTFields ISO = new SWTTFields("ISO", 1, 2); 
    public static readonly SWTTFields EPC = new SWTTFields("EPC", 3, 4); 

    private SWTTFields(String fieldName, Int32 startPositon, Int32 endPositon) 
    { 
     this.fieldName = fieldName; 
     this.startPosition = startPositon; 
     this.endPosition = endPositon; 
    } 
} 

Однако я складываю о назначении ссылки на два статических член. До сих пор я получил эту точку (ниже код в VB.NET, но я с удовольствием приму ответы в VB.NET или C#):

Dim typeBuilder As TypeBuilder = GetTypeBuilder() 

'Definition of three private variables 
'TODO: you need one more private field that would represent "Bank" particular field belongs to 

'Private String fieldName 
Dim fieldName As FieldBuilder = typeBuilder.DefineField("fieldName", 
                 GetType(String), 
                  FieldAttributes.Private) 
'Private Int32 startPosition 
Dim startPosition As FieldBuilder = typeBuilder.DefineField("startPosition", 
                  GetType(Int32), 
                   FieldAttributes.Private) 
'Private Int32 endPosition 
Dim endPosition As FieldBuilder = typeBuilder.DefineField("endPosition", 
                  GetType(Int32), FieldAttributes.Private) 

'Type is taken from the current TypeBuilder 
Dim ISO As FieldBuilder = typeBuilder.DefineField("ISO", typeBuilder.GetType, FieldAttributes.Public)               
Dim EPC As FieldBuilder = typeBuilder.DefineField("EPC", typeBuilder.GetType, FieldAttributes.Public) 

'Constructor parameters are 
Dim constructorParams() As Type = {GetType(String), GetType(Int32), GetType(Int32)} 

'constructor for the class 
Dim ctorBuilder As ConstructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public Or 
                    MethodAttributes.SpecialName Or 
                    MethodAttributes.RTSpecialName, 
                    CallingConventions.Standard, 
                    constructorParams) 

Dim objType As Type = Type.GetType("System.Object") 
'pulls out info about Object constructor. It will be called later 
Dim objCtor As ConstructorInfo = objType.GetConstructor(Type.EmptyTypes) 

'Generating code (some of the code and comments came from ConstructorBuilder class) 
Dim ctorIL As ILGenerator = ctorBuilder.GetILGenerator() 

'place "this" on the stack 
ctorIL.Emit(OpCodes.Ldarg_0) 
'Create instance of System.Object by invokign its ctor 
ctorIL.Emit(OpCodes.Call, objCtor) 

'store fieldName parameter 
ctorIL.Emit(OpCodes.Ldarg_0) 
ctorIL.Emit(OpCodes.Ldarg_1) 
ctorIL.Emit(OpCodes.Stfld, fieldName) 

'store startPosition 
ctorIL.Emit(OpCodes.Ldarg_0) 
ctorIL.Emit(OpCodes.Ldarg_2) 
ctorIL.Emit(OpCodes.Stfld, startPosition) 

'stored endPosition 
ctorIL.Emit(OpCodes.Ldarg_0) 
ctorIL.Emit(OpCodes.Ldarg_3) 
ctorIL.Emit(OpCodes.Stfld, endPosition) 
'Done. Return 
ctorIL.Emit(OpCodes.Ret) 

ответ

3

Я не использовал TypeBuilder себя, так что это больше подсказка, чем полный код, но в основном я считаю, что вы хотите TypeBuilder.DefineTypeInitializer, и выполняйте задания там.

Другими словами, думать о классе, глядя, как это, с точки зрения его статические члены:

public class SWTTFields 
{ 
    public static readonly SWTTFields ISO; 
    public static readonly SWTTFields EPC; 

    static SWTTFields() 
    { 
     ISO = new SWTTFields("ISO", 1, 2); 
     EPC = new SWTTFields("EPC", 3, 4); 
    } 
} 

(Это не точно эквивалентен исходному коду, из-за той разницей, что статический конструктор делает, но он достаточно близко.)

Похоже, вы уже знаете, как сгенерировать соответствующий ИЛ для тела инициализатора этого типа - просто рассматривайте его как любой другой метод/тело конструктора.

+0

Простите мое невежество, но я не вижу, как 'TypeBuilder.DefineTypeInitializer' отличается от' TypeBuilder.DefineConstructor'? – newprint

+1

@newprint: 'DefineTypeInitializer' создает статический конструктор. 'DefineConstructor' создает конструктор экземпляра. –

+0

@John Skeet Спасибо. Именование очень сбивает с толку. 'TypeBuilder.DefineStaticConstructor' будет звучать лучше. – newprint