冠逹小站

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

我们通过一个计算A+B的动态类来演示如何为一个动态类添加属性、构造函数、方法,以及在方法中使用类中定义的属性,按照惯例,我们先给出要实现的动态类的C#代码,然后再针对C#代码给出相应的实现,代码如下:

public class Add
{

    private int _a = 0;
    public int A
    {
        get { return _a; }
        set { _a = value; }
    }

    private int _b = 0;
    public int B
    {
        get { return _b; }
        set { _b = value; }
    }

    public Add(int a, int b)
    {
        _a = a;
        _b = b;
    }

    public int Calc()
    {
        return _a + _b;
    }
}

前面的步骤和之前的斐波那契实现相同,这里我们直接从属性的定义开始。首先,我们通过TypeBuilder对象的DefineField方法来定义私有字段_a和_b,并为它们设置默认值0,代码如下:

 

- 定义私有字段_a和_b

FieldBuilder fieldABuilder = typeBuilder.DefineField("_a", typeof(Int32), FieldAttributes.Private);
FieldBuilder fieldBBuilder = typeBuilder.DefineField("_b", typeof(Int32), FieldAttributes.Private);
fieldABuilder.SetConstant(0);
fieldBBuilder.SetConstant(0);

然后我们通过TypeBuilder对象的DefineProperty方法分别定义属性A、B;接着再通过PropertyBuilder的SetGetMethod和SetSetMethod方法设置它们的get和set方法,至于get和set方法的IL代码的生成则和普通的Method定义相同,这里只列出属性A的定义,属性B与A相同,代码如下:

 

- 定义公有属性A和B

PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(Int32), null);
PropertyBuilder propertyBBuilder = typeBuilder.DefineProperty("B", PropertyAttributes.None, typeof(Int32), null);

定义属性A的get和set方法

//定义属性A的get方法
MethodBuilder getPropertyABuilder = typeBuilder.DefineMethod("get",
                    MethodAttributes.Public
                    | MethodAttributes.SpecialName
                    | MethodAttributes.HideBySig,
                    typeof(Int32),
                    Type.EmptyTypes);

//生成属性A的get方法的IL代码,即返回私有字段_a
ILGenerator getAIL = getPropertyABuilder.GetILGenerator();
getAIL.Emit(OpCodes.Ldarg_0);
getAIL.Emit(OpCodes.Ldfld, fieldABuilder);
getAIL.Emit(OpCodes.Ret);

//定义属性A的set方法
MethodBuilder setPropertyABuilder = typeBuilder.DefineMethod("set",
                    MethodAttributes.Public
                    | MethodAttributes.SpecialName
                    | MethodAttributes.HideBySig,
                    null,
                    new Type[] { typeof(Int32) });

//生成属性A的set方法的IL代码,即设置私有字段_a值为传入的参数1的值
ILGenerator setAIL = setPropertyABuilder.GetILGenerator();
setAIL.Emit(OpCodes.Ldarg_0);
setAIL.Emit(OpCodes.Ldarg_1);
setAIL.Emit(OpCodes.Stfld, fieldABuilder);
setAIL.Emit(OpCodes.Ret);

//设置属性A的get和set方法
propertyABuilder.SetGetMethod(getPropertyABuilder);
propertyABuilder.SetSetMethod(setPropertyABuilder);

 

最后,我们来定义构造函数和Calc方法,构造函数的定义使用TypeBuilder的DefineConstructor方法,获得一个ConstructorBuilder对象,接下来就转入到跟普通的方法定义相同的步骤,代码如下:

 

定义构造函数和方法

- 定义构造函数

ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32), typeof(Int32) });

ILGenerator ctorIL = constructorBuilder.GetILGenerator();

//加载参数1填充到私有字段_a
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_1);
ctorIL.Emit(OpCodes.Stfld, fieldABuilder);
//加载参数2填充到私有字段_b
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_2);
ctorIL.Emit(OpCodes.Stfld, fieldBBuilder);
ctorIL.Emit(OpCodes.Ret);

 

- 定义方法

MethodBuilder calcMethodBuilder = typeBuilder.DefineMethod("Calc", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes);

ILGenerator calcIL = calcMethodBuilder.GetILGenerator();

//加载私有字段_a
calcIL.Emit(OpCodes.Ldarg_0);
calcIL.Emit(OpCodes.Ldfld, fieldABuilder);
//加载私有字段_b
calcIL.Emit(OpCodes.Ldarg_0);
calcIL.Emit(OpCodes.Ldfld, fieldBBuilder);
//相加并返回结果
calcIL.Emit(OpCodes.Add);
calcIL.Emit(OpCodes.Ret);

 

到这里,我们终于完成了动态类的创建

posted on 2011-03-28 21:24  林冠逹  阅读(1637)  评论(0编辑  收藏  举报