如何通过调用它的构造函数来发出代码以将 value/reference 分配给 class 的静态字段?
How to Emit code to assign value/reference to static field of class by calling it's constructor?
(我的代码有点乱七八糟的 C# 和 VB.NET)
我正在尝试发出如下所示的 class:
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)
我自己没有使用过 TypeBuilder
,所以这更像是一个提示,而不是完整的代码,但基本上我相信你想要 TypeBuilder.DefineTypeInitializer
,并在其中执行作业。
换句话说,就其静态成员而言,class 看起来像这样:
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);
}
}
(由于静态构造函数的不同,这并不完全等同于原始代码,但它已经足够接近了。)
看起来您已经知道如何为该类型的初始化程序主体生成相关的 IL - 就像对待任何其他 method/constructor 主体一样对待它。
(我的代码有点乱七八糟的 C# 和 VB.NET) 我正在尝试发出如下所示的 class:
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)
我自己没有使用过 TypeBuilder
,所以这更像是一个提示,而不是完整的代码,但基本上我相信你想要 TypeBuilder.DefineTypeInitializer
,并在其中执行作业。
换句话说,就其静态成员而言,class 看起来像这样:
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);
}
}
(由于静态构造函数的不同,这并不完全等同于原始代码,但它已经足够接近了。)
看起来您已经知道如何为该类型的初始化程序主体生成相关的 IL - 就像对待任何其他 method/constructor 主体一样对待它。