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