【转】Emit学习-基础篇-为动态类添加属性、构造函数、方法

我们通过一个计算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方法分别定义属性AB;接着再通过PropertyBuilderSetGetMethodSetSetMethod方法设置它们的getset方法,至于getset方法的IL代码的生成则和普通的Method定义相同,这里只列出属性A的定义,属性BA相同,代码如下:


//定义公有属性A和B

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

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

 

#region 定义属性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);

 

#endregion

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


#region Step 5 定义构造函数

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);

#endregion


#region Step 6 定义方法

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);

#endregion


到这里,我们终于完成了动态类的创建,最后,同样给出完整的源码下载 A+B,希望这系列的文章能够对大家有帮助。
posted @ 2009-08-03 14:54  JoeWang  阅读(378)  评论(0)    收藏  举报