FieldBuilder - 何设置默认值?
FieldBuilder - Ho do you set the default value?
我正在使用 TypeBuilder 在运行时创建类型,但似乎无法弄清楚如何设置字段的默认值。
例如,假设我想在运行时创建以下布局,使用 TypeBuilder,如何设置 'm_number' 的默认值(至 64)?
public class DynamicType1
{
private int m_number = 64;
public int Number
{
get { return m_number; }
set { m_number = value; }
}
}
这是我用来创建 属性 的代码,...如何将字段设置为 'defaultValue'
的值
void AddProperty(string name, Type type, object defaultValue)
{
// Add a private field of type
FieldBuilder fieldBuilder = m_typeBuilder.DefineField("m_" + name.ToLower(), type, FieldAttributes.Private);
// Define a property that gets and sets the private field. The last argument of DefineProperty is null, because the
// property has no parameters. (If you don't specify null, you must specify an array of Type objects. For a parameterless property,
// use the built-in array with no elements: Type.EmptyTypes)
PropertyBuilder propertyBuilder = m_typeBuilder.DefineProperty(name, PropertyAttributes.HasDefault, type, null);
// The property "set" and property "get" methods require a special set of attributes.
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
// Define the "get" accessor method. The method returns the value and has no arguments. (Note that null could be
// used instead of Types.EmptyTypes)
MethodBuilder getAccessorMethodBuilder = m_typeBuilder.DefineMethod("get_" + name, getSetAttr, type, Type.EmptyTypes);
// For an instance property, argument zero is the instance. Load the instance, then load the private
//field and return, leaving the field value on the stack.
ILGenerator numberGetIL = getAccessorMethodBuilder.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fieldBuilder);
numberGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for Number, which has no return type and takes one argument of type T.
MethodBuilder setAccessorMethodBuilder = m_typeBuilder.DefineMethod("set_" + name, getSetAttr, null, new Type[] { type });
// Load the instance and then the argument, then store the argument in the field.
ILGenerator numberSetIL = setAccessorMethodBuilder.GetILGenerator();
numberSetIL.Emit(OpCodes.Ldarg_0);
numberSetIL.Emit(OpCodes.Ldarg_1);
numberSetIL.Emit(OpCodes.Stfld, fieldBuilder);
numberSetIL.Emit(OpCodes.Ret);
// Last, map the "get" and "set" accessor methods to the PropertyBuilder. The property is now complete.
propertyBuilder.SetGetMethod(getAccessorMethodBuilder);
propertyBuilder.SetSetMethod(setAccessorMethodBuilder);
}
如有疑问,请在 IL 模式下询问 Roslyn :-) http://goo.gl/NebcEP
默认字段在对象的构造函数中设置:
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2061
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 64
IL_0003: stfld int32 DynamicType1::m_number
请注意,如果有多个构造函数,似乎链接到同一 class 的其他构造函数的构造函数不会设置值,而不会链接到同一构造函数的其他构造函数的构造函数class 设置。请参阅扩展示例:http://goo.gl/8y90kU
我正在使用 TypeBuilder 在运行时创建类型,但似乎无法弄清楚如何设置字段的默认值。
例如,假设我想在运行时创建以下布局,使用 TypeBuilder,如何设置 'm_number' 的默认值(至 64)?
public class DynamicType1
{
private int m_number = 64;
public int Number
{
get { return m_number; }
set { m_number = value; }
}
}
这是我用来创建 属性 的代码,...如何将字段设置为 'defaultValue'
的值void AddProperty(string name, Type type, object defaultValue)
{
// Add a private field of type
FieldBuilder fieldBuilder = m_typeBuilder.DefineField("m_" + name.ToLower(), type, FieldAttributes.Private);
// Define a property that gets and sets the private field. The last argument of DefineProperty is null, because the
// property has no parameters. (If you don't specify null, you must specify an array of Type objects. For a parameterless property,
// use the built-in array with no elements: Type.EmptyTypes)
PropertyBuilder propertyBuilder = m_typeBuilder.DefineProperty(name, PropertyAttributes.HasDefault, type, null);
// The property "set" and property "get" methods require a special set of attributes.
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
// Define the "get" accessor method. The method returns the value and has no arguments. (Note that null could be
// used instead of Types.EmptyTypes)
MethodBuilder getAccessorMethodBuilder = m_typeBuilder.DefineMethod("get_" + name, getSetAttr, type, Type.EmptyTypes);
// For an instance property, argument zero is the instance. Load the instance, then load the private
//field and return, leaving the field value on the stack.
ILGenerator numberGetIL = getAccessorMethodBuilder.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fieldBuilder);
numberGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for Number, which has no return type and takes one argument of type T.
MethodBuilder setAccessorMethodBuilder = m_typeBuilder.DefineMethod("set_" + name, getSetAttr, null, new Type[] { type });
// Load the instance and then the argument, then store the argument in the field.
ILGenerator numberSetIL = setAccessorMethodBuilder.GetILGenerator();
numberSetIL.Emit(OpCodes.Ldarg_0);
numberSetIL.Emit(OpCodes.Ldarg_1);
numberSetIL.Emit(OpCodes.Stfld, fieldBuilder);
numberSetIL.Emit(OpCodes.Ret);
// Last, map the "get" and "set" accessor methods to the PropertyBuilder. The property is now complete.
propertyBuilder.SetGetMethod(getAccessorMethodBuilder);
propertyBuilder.SetSetMethod(setAccessorMethodBuilder);
}
如有疑问,请在 IL 模式下询问 Roslyn :-) http://goo.gl/NebcEP
默认字段在对象的构造函数中设置:
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2061
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 64
IL_0003: stfld int32 DynamicType1::m_number
请注意,如果有多个构造函数,似乎链接到同一 class 的其他构造函数的构造函数不会设置值,而不会链接到同一构造函数的其他构造函数的构造函数class 设置。请参阅扩展示例:http://goo.gl/8y90kU