FieldBuilder - 您是否设置了默认值?

时间:2015-05-15 11:34:28

标签: c# dynamic default-value typebuilder

我正在使用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);
    }

1 个答案:

答案 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