using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Threading; namespace EmitCreateDynamicProxy { public class DynamicProxyGenerator { private const string DynamicAssemblyName = "DynamicAssembly";//动态程序集名称 private const string DynamicModuleName = "DynamicAssemblyModule"; private const string DynamicModuleDllName = "DynamicAssembly.dll";//动态模块名称 private const string ProxyClassNameFormater = "{0}Proxy"; private const string ModifiedPropertyNamesFieldName = "ModifiedPropertyNames"; private const MethodAttributes GetSetMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig; /// /// 创建动态程序集,返回AssemblyBuilder /// /// /// private static AssemblyBuilder DefineDynamicAssembly(bool isSavaDll = false) { //动态创建程序集 AssemblyName DemoName = new AssemblyName(DynamicAssemblyName); AssemblyBuilderAccess assemblyBuilderAccess = isSavaDll ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run; AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, assemblyBuilderAccess); return dynamicAssembly; } /// /// 创建动态模块,返回ModuleBuilder /// /// /// ModuleBuilder private static ModuleBuilder DefineDynamicModule(AssemblyBuilder dynamicAssembly, bool isSavaDll = false) { ModuleBuilder moduleBuilder = null; //动态创建模块 if (isSavaDll) moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName, DynamicModuleDllName); else moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName); return moduleBuilder; } /// /// 创建动态代理类,重写属性Get Set 方法,并监控属性的Set方法,把变更的属性名加入到list集合中,需要监控的属性必须是virtual /// 如果你想保存修改的属性名和属性值,修改Set方法的IL实现 /// /// /// /// public static T CreateDynamicProxy(bool isSavaDynamicModule = false) { Type modifiedPropertyNamesType = typeof(HashSet); Type typeNeedProxy = typeof(T); AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(isSavaDynamicModule); //动态创建模块 ModuleBuilder moduleBuilder = DefineDynamicModule(assemblyBuilder, isSavaDynamicModule); string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name); //动态创建类代理 TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy); //定义一个变量存放属性变更名 FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public); //定义接口 var pt = typeof(PropertyChangedEventHandler); typeBuilderProxy.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); var eil = typeBuilderProxy.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler)); //add field var eb = typeBuilderProxy.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private); var compareExchange = GetGenericMethod(typeof(Interlocked), "CompareExchange");// finds the correct method to call. // thanks to @marc, create the specific method with the correct type compareExchange = compareExchange.MakeGenericMethod(typeof(PropertyChangedEventHandler)); //add methoed var mas = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.Final; var mb = typeBuilderProxy.DefineMethod("add_PropertyChanged", mas, typeof(void), new Type[] { pt }); mb.DefineParameter(0, ParameterAttributes.Retval, null); mb.DefineParameter(1, ParameterAttributes.In, "value"); var il = mb.GetILGenerator(); il.DeclareLocal(pt); il.DeclareLocal(pt); il.DeclareLocal(pt); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, eb); il.Emit(OpCodes.Stloc_0); var lable = il.DefineLabel(); il.MarkLabel(lable); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) })); il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); il.Emit(OpCodes.Stloc_2); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldflda, eb); il.Emit(OpCodes.Ldloc_2); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Call, compareExchange); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Bne_Un_S, lable); il.Emit(OpCodes.Ret); //remove event mb = typeBuilderProxy.DefineMethod("remove_PropertyChanged", mas, typeof(void), new Type[] { pt }); mb.DefineParameter(0, ParameterAttributes.Retval, null); mb.DefineParameter(1, ParameterAttributes.In, "value"); il = mb.GetILGenerator(); il.DeclareLocal(pt); il.DeclareLocal(pt); il.DeclareLocal(pt); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, eb); il.Emit(OpCodes.Stloc_0); lable = il.DefineLabel(); il.MarkLabel(lable); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) })); il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); il.Emit(OpCodes.Stloc_2); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldflda, eb); il.Emit(OpCodes.Ldloc_2); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Call, compareExchange); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Bne_Un_S, lable); il.Emit(OpCodes.Ret); /* * 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码 ModifiedPropertyNames = new List(); */ ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); ILGenerator ilgCtor = constructorBuilder.GetILGenerator(); ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类 ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈 ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象 ilgCtor.Emit(OpCodes.Ret);//返回 //获取被代理对象的所有属性,循环属性进行重写 PropertyInfo[] properties = typeNeedProxy.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { string propertyName = propertyInfo.Name; Type typePepropertyInfo = propertyInfo.PropertyType; //动态创建字段和属性 FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private); PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null); //重写属性的Get Set方法 var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes); var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, null, new Type[] { typePepropertyInfo }); //il of get method var ilGetMethod = methodGet.GetILGenerator(); ilGetMethod.Emit(OpCodes.Ldarg_0); ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder); ilGetMethod.Emit(OpCodes.Ret); //il of set method ILGenerator ilSetMethod = methodSet.GetILGenerator(); var nullLabel = ilSetMethod.DefineLabel(); ilSetMethod.Emit(OpCodes.Ldarg_0); ilSetMethod.Emit(OpCodes.Ldarg_1); ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder); ilSetMethod.Emit(OpCodes.Ldarg_0); ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames); ilSetMethod.Emit(OpCodes.Dup); ilSetMethod.Emit(OpCodes.Brtrue_S, nullLabel); ilSetMethod.Emit(OpCodes.Pop); var retLabel = ilSetMethod.DefineLabel(); ilSetMethod.Emit(OpCodes.Br_S, retLabel); ilSetMethod.MarkLabel(nullLabel); ilSetMethod.Emit(OpCodes.Ldarg_0); ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name); ilSetMethod.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs)); ilSetMethod.Emit(OpCodes.Callvirt, pt.GetMethod("Invoke", new Type[] { typeof(object), typeof(PropertyChangedEventArgs) })); ilSetMethod.Emit(OpCodes.Nop); il.MarkLabel(retLabel); ilSetMethod.Emit(OpCodes.Ret); //设置属性的Get Set方法 propertyBuilder.SetGetMethod(methodGet); propertyBuilder.SetSetMethod(methodSet); } //使用动态类创建类型 Type proxyClassType = typeBuilderProxy.CreateType(); //保存动态创建的程序集 if (isSavaDynamicModule) assemblyBuilder.Save(DynamicModuleDllName); //创建类实例 var instance = Activator.CreateInstance(proxyClassType); return (T)instance; } /// /// 获取属性的变更名称, /// 此处只检测调用了Set方法的属性,不会检测值是否真的有变 /// /// /// public static HashSet GetModifiedProperties(object obj) { FieldInfo fieldInfo = obj.GetType().GetField(ModifiedPropertyNamesFieldName); if (fieldInfo == null) return null; object value = fieldInfo.GetValue(obj); return value as HashSet; } private static MethodInfo GetGenericMethod(Type type, string methodName) { var q = from m in type.GetMethods() where m.Name == methodName && m.IsGenericMethod select m; return q.FirstOrDefault(); } } }