最近项目中反射用的很多,担心在性能上会下降太多,所以在下班时间尝试着写了个小例子,来提高反射的性能。
目标:必须支持任意对象类型的目标(Target) 和对象所持有的属性名(PropertyName),能得到对应的属性值
主要思路是将 属性的Get()方法 转换成委托,再把委托存到字典里,需要反射的时候直接去字典里找对应的委托并调用它;
public class Model
{
//类初始化的时候就吧Get方法都存好
public void Init()
{
Type type = this.GetType();
//尝试添加该类到子类列表里,且属性列表不为空
if (DelegateReflect_TwoDictionary.TypeList.TryAdd(type)&&this.PropertyNames!=null)
{
//如果添加成功,说明是第一次添加
ConcurrentDictionary<string, object> Dictionary = new ConcurrentDictionary<string, object>();
foreach(var item in this.PropertyNames)
{
var GetMethod = DelegateReflect_TwoDictionary.GetPropertyGetMethod(type, item);
if (GetMethod != null)
{
Dictionary.TryAdd(item, GetMethod);
}
}
DelegateReflect_TwoDictionary.ClassDictionary.TryAdd(type, Dictionary);
}
}
//需要提前获得get委托的属性名列表
public virtual List<string> PropertyNames
{
get { return null; }
}
}
public class A : Model
{
public string Name { set; get; }
public bool Y { set; get; }
public double[] W { set; get; }
public override List<string> PropertyNames {
get{
return new List<string>(){"Name","Y","W"};
}
}
public A()
{
base.Init();
}
}
public class B :Model
{
public object Age { set; get; }
public double X { set; get; }
public List<int> J { set; get; }
public Collection<bool> K { set; get; }
public override List<string> PropertyNames
{
get
{
return new List<string>() { "Age", "X", "J","K" };
}
}
public B()
{
base.Init();
}
}
/// <summary>
/// 设计模式 模板方法
/// </summary>
public abstract class Algorithm {
//循环次数
public static int LoopTime;
public void TestTime(string AlgorithmName,object Target,string PropertyName)
{
this.PreOpration(Target,PropertyName);
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
for(int i = 0; i < LoopTime; i++)
{
ExecuteAlgorithm(Target, PropertyName);
}
stopwatch.Stop();
Console.WriteLine("使用"+AlgorithmName + "执行的时间:" + stopwatch.Elapsed.TotalMilliseconds + "ms");
}
//算法测试前的准备(预热)
public virtual void PreOpration(object Target, string PropertyName)
{
}
//算法正式执行(单次)
public abstract void ExecuteAlgorithm(object Target,string PropertyName);
}
/// <summary>
/// 反射委托类-双并发字典
/// </summary>
/// <typeparam name="T"></typeparam>
public static class DelegateReflect_TwoDictionary {
//支持返回值为Double类型的委托
public delegate double GetDoubleValue<T>(T Target);
//支持返回值为Double类型的委托
public delegate int GetIntValue<T>(T Target);
//支持返回值为对象类型的委托
public delegate object GetObjectValue<T>(T Target);
//支持返回值为bool类型的委托
public delegate bool GetBoolValue<T>(T Target);
public static BlockingCollection<Type> TypeList = new BlockingCollection<Type>();
//反射字典,Type是 类的Type
public static ConcurrentDictionary<Type, ConcurrentDictionary<string, object>> ClassDictionary
= new ConcurrentDictionary<Type, ConcurrentDictionary<string, object>>();
/// <summary>
/// 反射 只根据 Object和属性名
/// </summary>
/// <param name="Target"></param>
/// <param name="PropertyName"></param>
/// <returns></returns>
public static object FastGetValue(object Target, string PropertyName)
{
Type TargetType = Target.GetType();
object get = null;
ConcurrentDictionary<string, object> PropertyDictionary = null;
if (!ClassDictionary.TryGetValue(TargetType, out PropertyDictionary))
{
PropertyDictionary = new ConcurrentDictionary<string, object>();
ClassDictionary.TryAdd(TargetType, PropertyDictionary);
}
if (!PropertyDictionary.TryGetValue(PropertyName, out get))
{
PropertyInfo propertyInfo = TargetType.GetProperty(PropertyName);
MethodInfo GetMethod = propertyInfo.GetGetMethod();
Type DelegateType = null;
if (propertyInfo.PropertyType == typeof(int))
{
//动态指定泛型的类型
DelegateType = typeof(GetIntValue<>).MakeGenericType(TargetType);
}
else if (propertyInfo.PropertyType == typeof(double))
{
//动态指定泛型的类型
DelegateType = typeof(GetDoubleValue<>).MakeGenericType(TargetType);
}
else if (propertyInfo.PropertyType == typeof(bool))
{
//动态指定泛型的类型
DelegateType = typeof(GetBoolValue<>).MakeGenericType(TargetType);
}
else
{
//动态指定泛型的类型
DelegateType = typeof(GetObjectValue<>).MakeGenericType(TargetType);
}
get = Delegate.CreateDelegate(DelegateType, GetMethod);
PropertyDictionary.TryAdd(PropertyName, get);
}
dynamic x = get;
dynamic y = Target;
return x(y);
}
//获得某个属性的Get方法
public static object GetPropertyGetMethod(Type TargetType,string PropertyName)
{
PropertyInfo propertyInfo = TargetType.GetProperty(PropertyName);
object get = null;
if (propertyInfo != null && propertyInfo.CanRead)
{
MethodInfo GetMethod = propertyInfo.GetGetMethod();
Type DelegateType = null;
if (propertyInfo.PropertyType == typeof(int))
{
//动态指定泛型的类型
DelegateType = typeof(GetIntValue<>).MakeGenericType(TargetType);
}
else if (propertyInfo.PropertyType == typeof(double))
{
//动态指定泛型的类型
DelegateType = typeof(GetDoubleValue<>).MakeGenericType(TargetType);
}
else if (propertyInfo.PropertyType == typeof(bool))
{
//动态指定泛型的类型
DelegateType = typeof(GetBoolValue<>).MakeGenericType(TargetType);
}
else
{
//动态指定泛型的类型
DelegateType = typeof(GetObjectValue<>).MakeGenericType(TargetType);
}
get = Delegate.CreateDelegate(DelegateType, GetMethod);
}
return get;
}
}
/// <summary>
/// 反射委托类-单并发字典
/// </summary>
//委托反射
public class DelegateAlgorithm_TwoDictionary : Algorithm {
public override void PreOpration(object Target, string PropertyName)
{
// var result = DelegateReflect_TwoDictionary.FastGetValue(Target, PropertyName);
}
public override void ExecuteAlgorithm(object Target, string PropertyName)
{
var result = DelegateReflect_TwoDictionary.FastGetValue(Target, PropertyName);
}
}
//直接调用
public class StraightInvoke : Algorithm {
public override void ExecuteAlgorithm(object Target, string PropertyName)
{
var result = ((A)Target).Name;
}
}
//纯反射
public class Reflect : Algorithm
{
public override void ExecuteAlgorithm(object Target, string PropertyName)
{
Type type = Target.GetType();
PropertyInfo property = type.GetProperty(PropertyName);
if (property != null&&property.CanRead)
{
var result = property.GetValue(Target);
}
}
}
class Program
{
static void Main(string[] args)
{
Algorithm.LoopTime = 1000;
A a = new A() { Name = "fangxiang",Y=true,W=new double[4] };
B b = new B() { Age = 1 ,X=2};
Algorithm Delegate = new DelegateAlgorithm_TwoDictionary();
Delegate.TestTime("委托反射-双字典",a,"Name");
Delegate.TestTime("委托反射-双字典", a, "Y");
Delegate.TestTime("委托反射-双字典", a, "W");
Delegate.TestTime("委托反射-双字典", b, "Age");
Delegate.TestTime("委托反射-双字典", b, "X");
Delegate.TestTime("委托反射-双字典", b, "J");
Delegate.TestTime("委托反射-双字典", b, "K");
Algorithm Reflect = new Reflect();
Reflect.TestTime("纯反射", a, "Name");
Reflect.TestTime("纯反射", a, "Y");
Reflect.TestTime("纯反射", a, "W");
Reflect.TestTime("纯反射", b, "Age");
Reflect.TestTime("纯反射", b, "X");
Reflect.TestTime("纯反射", b, "J");
Reflect.TestTime("纯反射", b, "K");
Algorithm StraightInvoke = new StraightInvoke();
Console.ReadKey();
}
}