Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
namespace demo1
{
class Program
{
static void Main(string[] args)
{
//创建程序集“DynamicAssembly”
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("DynamicAssembly")//
, AssemblyBuilderAccess.Run //该程序集只用作运行,你还可以创建可保存的程序集
);
//创建模块“DynamicModule”
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
//创建类型“DynamicClass”
TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicClass"
, TypeAttributes.Public | TypeAttributes.Class //相当于 public class DynamicClass
, null //基类
, null //接口
);
//为类型增加一个方法“Greet”
MethodBuilder methodBuilder = typeBuilder.DefineMethod("Greet"
, MethodAttributes.Public
);
//获得ILGenerator对象,该对象用来为方法注入IL语言
ILGenerator g = methodBuilder.GetILGenerator();
//将字符串"HelloWorld"放到堆栈顶端
g.Emit(OpCodes.Ldstr, "HelloWorld");
//调用Console.WriteLine打印堆栈顶端的值
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine"
, BindingFlags.Public | BindingFlags.Static
, null
, new Type[] { typeof(string) }
, null));
//return
g.Emit(OpCodes.Ret);
//创建动态类型
Type type = typeBuilder.CreateType();
//实例化类型
object target = Activator.CreateInstance(type);
//获得Greet方法的描述
MethodInfo mi = type.GetMethod("Greet");
//调用方法
mi.Invoke(target, null);
}
}
}
Code
using System.Collections.Generic;
using System;
using System.Reflection.Emit;
using System.Reflection;
namespace demo2
{
/// <summary>
/// 描述一个属性容器,属性对象会实现这个接口
/// </summary>
public interface IPropertyContainer
{
/// <summary>
/// 获得属性名称列表
/// </summary>
IEnumerable<string> PropertyNames { get; }
/// <summary>
/// 设置或获得属性值
/// </summary>
/// <param name="key">属性名</param>
/// <returns></returns>
object this[string key] { get; set; }
}
/// <summary>
/// 工具类
/// </summary>
public static class ObjectWrappeerBuilder
{
/// <summary>
/// 设置动作执行前调用
/// </summary>
/// <param name="name">属性名</param>
/// <param name="value">属性值</param>
/// <returns>返回true才执行设置,否则不执行</returns>
public delegate bool PrevSet(string name, object value);
/// <summary>
/// 设置动作成功后代用
/// </summary>
/// <param name="name">属性名</param>
/// <param name="value">属性值</param>
public delegate void PostSet(string name, object value);
/// <summary>
/// 创建动态对象
/// </summary>
/// <param name="propObj">源对象</param>
/// <param name="prevSet">设置前置动作</param>
/// <param name="postSet">设置后置动作</param>
/// <returns>返回动态对象</returns>
public static object Build(IPropertyContainer propObj, PrevSet prevSet, PostSet postSet)
{
//创建一个动态程序集“DynamicAssembly”
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("DynamicAssembly")
, AssemblyBuilderAccess.Run);
//为程序集增加一个模块“DynamicModule”
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
//创建一个动态类型“”
TypeBuilder typeBuilder = moduleBuilder.DefineType(propObj.GetType().Name + "PropertiesWrapper"
, TypeAttributes.NotPublic | TypeAttributes.Class //这里设置类型的属性:非public 的class类型
, typeof(object) //这里设置基本类为object,因为需要调用基类构造函数
, null);
//为类型增加一个成员变量“element”,IPropertyContainer
FieldBuilder eleFB = typeBuilder.DefineField("element", propObj.GetType()
, System.Reflection.FieldAttributes.Private);
//为类型增加一个成员变量“prevSet”,PrevSet
FieldBuilder prevSetFB = typeBuilder.DefineField("prevSet", prevSet.GetType()
, System.Reflection.FieldAttributes.Private);
//为类型增加一个成员变量“postSet”,PostSet
FieldBuilder postSetFB = typeBuilder.DefineField("postSet", postSet.GetType()
, System.Reflection.FieldAttributes.Private);
//将键值对添加成类型的property
foreach (string key in propObj.PropertyNames)
{
BuildProperty(propObj, typeBuilder, prevSet, prevSetFB, postSet
, postSetFB, eleFB, key, propObj[key]);
}
//获得类型数组,一般在各种反射函数中
Type[] argTypes = new Type[] { propObj.GetType(), prevSet.GetType(), postSet.GetType() };
//定义构造函数,我们要用这种方式将外部值传给动态类型
ConstructorBuilder defCtorBuilder
= typeBuilder.DefineConstructor(MethodAttributes.Public
, CallingConventions.Standard
, argTypes //我们刚定义的类型数组在这里描述了构造函数的参数列表
);
//获得构造函数的ILGenerator
ILGenerator cilg = defCtorBuilder.GetILGenerator();
//获得基类构造函数
ConstructorInfo objCtor = Type.GetType("System.Object").GetConstructor(new Type[0]);
//下面的IL代码可以翻译成:
/*
* ctor(IPropertyContainer propObj, PrevSet prevSet, PostSet postSet)
* :base()
* {
* this.element = propObj;
* this.prevSet = prevSet;
* this.postSet = postSet;
* }
* */
cilg.Emit(OpCodes.Ldarg_0);
cilg.Emit(OpCodes.Call, objCtor);
cilg.Emit(OpCodes.Ldarg_0);
cilg.Emit(OpCodes.Ldarg_1);
cilg.Emit(OpCodes.Stfld, eleFB);
cilg.Emit(OpCodes.Ldarg_0);
cilg.Emit(OpCodes.Ldarg_2);
cilg.Emit(OpCodes.Stfld, prevSetFB);
cilg.Emit(OpCodes.Ldarg_0);
cilg.Emit(OpCodes.Ldarg_3);
cilg.Emit(OpCodes.Stfld, postSetFB);
cilg.Emit(OpCodes.Ret);
//创建类型
Type type = typeBuilder.CreateType();
//创建实例
return Activator.CreateInstance(type, new object[] { propObj, prevSet, postSet }, null);
}
/// <summary>
/// 这是一个辅助函数,将键值对变成一个property
/// </summary>
/// <param name="propObj">源对象</param>
/// <param name="typeBuilder">类型描述</param>
/// <param name="prevSet">调用前事件代理</param>
/// <param name="prevSetFB">调用前事件成员变量描述</param>
/// <param name="postSet">调用后事件代理</param>
/// <param name="postSetFB">调用后事件成员变量描述</param>
/// <param name="eleFB">源对象成员变量描述</param>
/// <param name="key">键</param>
/// <param name="val">值</param>
private static void BuildProperty(IPropertyContainer propObj, TypeBuilder typeBuilder
, PrevSet prevSet, FieldBuilder prevSetFB, PostSet postSet, FieldBuilder postSetFB
, FieldBuilder eleFB, string key, object val)
{
//定义一个property
PropertyBuilder propBuilder = typeBuilder.DefineProperty(key
, System.Reflection.PropertyAttributes.None, val.GetType(), null);
//定义一个函数用作property的get函数
MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + key,
MethodAttributes.Public,
val.GetType(), new Type[] { });
//获得该函数ILGenerator
ILGenerator ilg = getMethodBuilder.GetILGenerator();
//获得IPropertyContainer的property: this[string key],的描述
PropertyInfo pi = typeof(IPropertyContainer).GetProperty("Item", new Type[] { typeof(string) });
//下面的IL代码可以翻译成:
/*
* get
* {
* return element[key];
* }
* */
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldfld, eleFB);
ilg.Emit(OpCodes.Ldstr, key);
ilg.EmitCall(OpCodes.Call, pi.GetGetMethod(), null);
ilg.Emit(OpCodes.Ret);
//将该函数设置为property的get函数
propBuilder.SetGetMethod(getMethodBuilder);
//定义一个函数用作property的set函数
MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + key,
MethodAttributes.Public,
null, new Type[] { val.GetType() });
//获得该函数ILGenerator
ilg = setMethodBuilder.GetILGenerator();
//下面的IL代码可以翻译成:
/*
* set
* {
* if(this.prevSet(value))
* {
* this.element[key] = value;
* this.postSet(value);
* }
* }
*
* 特别说明一下,大家会发现经常出现一个ilg.Emit(OpCodes.Ldarg_0);的调用
* 其实这是在将this指针放到堆栈顶端,因为非静态的成员函数的第一个参数其实
* 就是this指针,因此只要你需要引用成员都需要先调用这段代码。如果有Python
* 的开发经验对这个就不难理解了。
*/
System.Reflection.Emit.Label get_out = ilg.DefineLabel();
////调用前置函数,判断是否允许设置
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldfld, prevSetFB);
ilg.Emit(OpCodes.Ldstr, key);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Call, prevSet.GetType().GetMethod("Invoke"));
ilg.Emit(OpCodes.Brfalse, get_out);//如果为false跳转至get_out
//调用设置函数
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldfld, eleFB);
ilg.Emit(OpCodes.Ldstr, key);
ilg.Emit(OpCodes.Ldarg_1);
ilg.EmitCall(OpCodes.Callvirt, pi.GetSetMethod(), null);
//调用后置函数
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldfld, postSetFB);
ilg.Emit(OpCodes.Ldstr, key);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Call, postSet.GetType().GetMethod("Invoke"));
ilg.MarkLabel(get_out);
ilg.Emit(OpCodes.Ret);
//将该函数设置为property的set函数
propBuilder.SetSetMethod(setMethodBuilder);
}
}
}