第一篇:https://blog.youkuaiyun.com/Vblegend_2013/article/details/85228041
本章
_changepropertys 设为私有对象
构建代理对象时继承了IPropertyChanged,实现了两个方法 保证了效率问题
获取更新记录数
获取更新字段信息
public interface IPropertyChanged
{
Int32 GetChangedCount();
IEnumerable<KeyValuePair<String, Object>> GetAndResetChanges();
}
反编译后的生成代理类
using System;
using System.Collections.Generic;
using System.Linq;
using WindowsFormsApp1;
public class Person : WindowsFormsApp1.Person, IPropertyChanged
{
private Dictionary<string, object> ChangePropertys = new Dictionary<string, object>();
private string _name;
private int _age;
public override string Name
{
get
{
return this._name;
}
set
{
bool flag = this._name != value;
if (flag)
{
this._name = value;
this.ChangePropertys["Name"] = value;
}
}
}
public override int Age
{
get
{
return this._age;
}
set
{
bool flag = this._age != value;
if (flag)
{
this._age = value;
this.ChangePropertys["Age"] = value;
}
}
}
public override IEnumerable<KeyValuePair<string, object>> GetAndResetChanges()
{
KeyValuePair<string, object>[] result = this.ChangePropertys.ToArray<KeyValuePair<string, object>>();
this.ChangePropertys.Clear();
return result;
}
public override int GetChangedCount()
{
return this.ChangePropertys.Count;
}
}
测试代码
using System;
using System.Diagnostics;
using System.Linq;
namespace WindowsFormsApp1
{
class Program
{
static void Main(string[] args)
{
DynamicProxyGenerator dpg = new DynamicProxyGenerator("DynamicAssembly");
//注册类型
dpg.Register<Person>();
dpg.Register<Person2>();
//保存为dll
dpg.Save();
Person p = dpg.CreateInstance<Person>();
p.Name = "tom";
p.Age = 12345;
Console.WriteLine($"第一次检测改变了{DynamicProxyGenerator.GetChangedCount(p)}");
var changes = DynamicProxyGenerator.GetAndResetChanges(p);
Console.WriteLine($"第一次检测改变了{changes.Count()}个属性");
p.Name = "tony";
p.Age = 12345;
Console.WriteLine($"第二次检测改变了{DynamicProxyGenerator.GetChangedCount(p)}");
changes = DynamicProxyGenerator.GetAndResetChanges(p);
Console.WriteLine($"第二次检测改变了{changes.Count()}个属性");
//创建对象测试
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
var p2 = dpg.CreateInstance<Person2>();
}
stopwatch.Stop();
Console.WriteLine($"创建对象100000个用时{stopwatch.ElapsedMilliseconds}ms");
Console.ReadKey();
}
}
public class Person
{
public virtual String Name { get; set; }
public virtual Int32 Age { get; set; }
}
public class Person2
{
public virtual String Name { get; set; }
public virtual Int32 Age { get; set; }
}
}
代理类生成器
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace WindowsFormsApp1
{
/// <summary>
/// 属性改变接口
/// </summary>
public interface IPropertyChanged
{
Int32 GetChangedCount();
IEnumerable<KeyValuePair<String, Object>> GetAndResetChanges();
}
/// <summary>
/// 动态代理类生成器
/// </summary>
public class DynamicProxyGenerator
{
/// <summary>
/// 改变属性数据集
/// </summary>
private const string ModifiedPropertyNamesFieldName = "_changepropertys";
/// <summary>
/// 重写方法属性
/// </summary>
private const MethodAttributes GetSetMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig;
/// <summary>
/// 程序集名称
/// </summary>
private AssemblyName assemblyName { get; set; }
/// <summary>
/// 程序集构建器
/// </summary>
private AssemblyBuilder assemblyBuilder { get; set; }
/// <summary>
/// 程序集模块
/// </summary>
private ModuleBuilder moduleBuilder { get; set; }
/// <summary>
/// 保存修改属性的集合类型
/// </summary>
private Type modifiedPropertyNamesType { get; set; }
/// <summary>
/// 构造一个动态代理生成器
/// </summary>
/// <param name="AssemblyName"></param>
/// <param name="isSaveDynamicModule"></param>
public DynamicProxyGenerator(String DynamicAssemblyName)
{
//创建程序集
assemblyName = new AssemblyName(DynamicAssemblyName);
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
//动态创建模块
moduleBuilder = assemblyBuilder.DefineDynamicModule(String.Format("{0}Module", DynamicAssemblyName), String.Format("{0}.dll", DynamicAssemblyName));
//修改的属性集合类型
modifiedPropertyNamesType = typeof(Dictionary<String, Object>);
}
/// <summary>
/// 注册类型到代理生成器(只注册Virtual属性)
/// </summary>
/// <typeparam name="T">类</typeparam>
/// <returns></returns>
public void Register<T>()
{
Type typeNeedProxy = typeof(T);
//创建动态类代理,这里名字不变 继承自T
TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(typeNeedProxy.Name, TypeAttributes.Public, typeNeedProxy, new Type[] { typeof(IPropertyChanged) });
//定义一个Dictionary变量存放属性变更名
FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Private);
/*
* 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码
ModifiedPropertyNames = new List<string>();
*/
#region constructor
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);//返回
#endregion
#region interface
#region GetAndResetChanges
var getandreset = typeBuilderProxy.DefineMethod("GetAndResetChanges", GetSetMethodAttributes, typeof(IEnumerable<KeyValuePair<String, Object>>), Type.EmptyTypes);
ILGenerator ilgetreset = getandreset.GetILGenerator();
ilgetreset.DeclareLocal(typeof(KeyValuePair<String, Object>[]));
ilgetreset.DeclareLocal(typeof(IEnumerable<KeyValuePair<String, Object>>));
//声明一个标签,标记到ret
Label lab1d = ilgetreset.DefineLabel();
ilgetreset.Emit(OpCodes.Nop);
ilgetreset.Emit(OpCodes.Ldarg_0);
ilgetreset.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
var toarray = typeof(System.Linq.Enumerable).GetMethod("ToArray");
toarray = toarray.MakeGenericMethod(typeof(KeyValuePair<String, Object>));
ilgetreset.Emit(OpCodes.Call, toarray);
ilgetreset.Emit(OpCodes.Stloc_0);
ilgetreset.Emit(OpCodes.Ldarg_0);
ilgetreset.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
ilgetreset.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("Clear", new Type[0]));
ilgetreset.Emit(OpCodes.Nop);
ilgetreset.Emit(OpCodes.Ldloc_0);
ilgetreset.Emit(OpCodes.Stloc_1);
ilgetreset.Emit(OpCodes.Br_S, lab1d);
ilgetreset.MarkLabel(lab1d);
ilgetreset.Emit(OpCodes.Ldloc_1);
ilgetreset.Emit(OpCodes.Ret);
#endregion
#region GetChangedCount
var getchangedcount = typeBuilderProxy.DefineMethod("GetChangedCount", GetSetMethodAttributes, typeof(Int32), Type.EmptyTypes);
ILGenerator ilgetcount = getchangedcount.GetILGenerator();
ilgetcount.DeclareLocal(typeof(Int32));
//声明一个标签,标记到ret
Label lab0f = ilgetcount.DefineLabel();
ilgetcount.Emit(OpCodes.Nop);
ilgetcount.Emit(OpCodes.Ldarg_0);
ilgetcount.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
ilgetcount.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("get_Count", new Type[0]));
ilgetcount.Emit(OpCodes.Stloc_0);
ilgetcount.Emit(OpCodes.Br_S, lab0f);
ilgetcount.MarkLabel(lab0f);
ilgetcount.Emit(OpCodes.Ldloc_0);
ilgetcount.Emit(OpCodes.Ret);
#endregion
#endregion
#region Build Proxy Property
//获取被代理对象的所有属性,循环属性进行重写
PropertyInfo[] properties = typeNeedProxy.GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
string propertyName = propertyInfo.Name;
Type typePepropertyInfo = propertyInfo.PropertyType;
//动态创建字段和属性
FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName.ToLower(), typePepropertyInfo, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null);
//重写属性的Get Set方法
#region Method Get
//il of get method
var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes);
var ilGetMethod = methodGet.GetILGenerator();
ilGetMethod.Emit(OpCodes.Ldarg_0);
ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder);
ilGetMethod.Emit(OpCodes.Ret);
#endregion
#region Method Set
var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, null, new Type[] { typePepropertyInfo });
//il of set method
ILGenerator ilSetMethod = methodSet.GetILGenerator();
//声明布尔类型
ilSetMethod.DeclareLocal(typeof(Boolean));
//声明一个标签,标记到ret
Label label = ilSetMethod.DefineLabel();
//判断值是否改变
ilSetMethod.Emit(OpCodes.Nop);
ilSetMethod.Emit(OpCodes.Ldarg_0);
ilSetMethod.Emit(OpCodes.Ldfld, fieldBuilder);
ilSetMethod.Emit(OpCodes.Ldarg_1);
ilSetMethod.Emit(OpCodes.Ceq);
ilSetMethod.Emit(OpCodes.Ldc_I4_0);
ilSetMethod.Emit(OpCodes.Ceq);
ilSetMethod.Emit(OpCodes.Stloc_0);
ilSetMethod.Emit(OpCodes.Ldloc_0);
//如果未改变,调到结束return
ilSetMethod.Emit(OpCodes.Brfalse_S, label);
//赋值
ilSetMethod.Emit(OpCodes.Nop);
ilSetMethod.Emit(OpCodes.Ldarg_0);
ilSetMethod.Emit(OpCodes.Ldarg_1);
ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder);
//保存到 Dictionary
ilSetMethod.Emit(OpCodes.Ldarg_0);
ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name);
ilSetMethod.Emit(OpCodes.Ldarg_1);
ilSetMethod.Emit(OpCodes.Box, propertyInfo.PropertyType);
ilSetMethod.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("set_Item", new Type[] { typeof(string), typeof(Object) }));
ilSetMethod.Emit(OpCodes.Nop);
ilSetMethod.Emit(OpCodes.Nop);
ilSetMethod.MarkLabel(label);
ilSetMethod.Emit(OpCodes.Ret);
//设置属性的Get Set方法
#endregion
propertyBuilder.SetGetMethod(methodGet);
propertyBuilder.SetSetMethod(methodSet);
}
#endregion
//引用下, 要不无法生成
Type proxyClassType = typeBuilderProxy.CreateType();
}
/// <summary>
/// 保存程序集到dll文件
/// </summary>
public void Save()
{
assemblyBuilder.Save($"{assemblyName.Name}.dll");
}
/// <summary>
/// 创建实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T CreateInstance<T>()
{
Type typeNeedProxy = typeof(T);
return (T)assemblyBuilder.CreateInstance(typeNeedProxy.Name);
}
/// <summary>
/// 获取属性的变更名称,
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<String, Object>> GetAndResetChanges<T>(T obj)
{
var instance = obj as IPropertyChanged;
if (instance == null)
{
throw new ArgumentException("obj IPropertyChanged");
}
return instance.GetAndResetChanges();
}
/// <summary>
/// 获取改变记录数
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static Int32 GetChangedCount<T>(T obj)
{
var instance = obj as IPropertyChanged;
if (instance == null)
{
throw new ArgumentException("obj IPropertyChanged");
}
return instance.GetChangedCount();
}
/// <summary>
/// 转换为IPropertyChanged;
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public IPropertyChanged ByPropertyChanged<T>(T obj)
{
return obj as IPropertyChanged;
}
}
}