现在的位置: 首页 > 综合 > 正文

Emit生成Property

2013年05月02日 ⁄ 综合 ⁄ 共 1970字 ⁄ 字号 评论关闭

最近在ORM的实现当中碰到一个新的需求:映射一个接口或者抽象类. 问题可以简单描述为:为一个接口或抽象类生成属性的具体实现,据个例子:
有接口如下

public interface IPerson
{
    int Age{get;set;}
    string Name{get;set;}
}

那么我们需要动态的生成以下这样一个类

public class Impl_Person:IPerson
{
    protected int m_Age;
    public int Age
    {
        get{return m_Age;}
        set{m_Age=value;}
    }

    protected int m_Name;
    public string Name
    {
        get{return m_Name;}
        set{m_Name=value;}
    }
}

解决方法有很多,我选择用Emit实现,关于Emit,网上简单的例子非常多,我只把重要的一些代码列出来:
PropertyInfo propInfo;//假设已经用反射获得某个porroperty的属性
TypeBuilder typeBuilder;//假设前面代码已经定义

//构造私有/保护成员(field)
FieldBuilder fieldBuilder = typeBuilder.DefineField("m_"+ propInfo.Name, propInfo.PropertyType, FieldAttributes.Private);

//开始构造property
PropertyBuilder propBuilder = typeBuilder.DefineProperty(propInfo.Name, PropertyAttributes.HasDefault, propInfo.PropertyType, null);

//get,set的属性(在这里可以看到get和set在.NET里面其实是一种特殊的method)
MethodAttributes methodAttribute = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MehodAttributes.Virtual;

//生成方法构造器
MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_"+ propInfo.Name, methodAttribute, propInfo.PropertyType, Type.EmptyTypes);

                ILGenerator getILGen = getMethodBuilder.GetILGenerator();

                //以下3行是IL,是get_XXX方法里面的具体代码
                getILGen.Emit(OpCodes.Ldarg_0);
                getILGen.Emit(OpCodes.Ldfld, fieldBuilder);
                getILGen.Emit(OpCodes.Ret);

                propBuilder.SetGetMethod(getMethodBuilder);//不要遗漏这句哦,普通的method是不需要这句的

MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propInfo.Name, methodAttribute, null, new Type[] { propInfo.PropertyType });

                ILGenerator setILGen = setMethodBuilder.GetILGenerator();

                //以下四行是IL,是set_XXX方法里面的具体代码
                setILGen.Emit(OpCodes.Ldarg_0);
                setILGen.Emit(OpCodes.Ldarg_1);
                setILGen.Emit(OpCodes.Stfld, fieldBuilder);
                setILGen.Emit(OpCodes.Ret);

                propBuilder.SetSetMethod(setMethodBuilder);

抱歉!评论已关闭.