我正在使用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);
}
答案 0 :(得分:0)
如有疑问,请以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
请注意,如果有多个构造函数,那么链接到同一个类的其他构造函数的构造函数似乎不会设置该值,而不链接到同一个类的其他构造函数的构造函数会设置。请参阅扩展示例:http://goo.gl/8y90kU