直接看代码
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
namespace Expression_表达式树_
{
/// <summary>
/// 泛型缓存机制
/// </summary>
/// <typeparam name="TIn"></typeparam>
/// <typeparam name="TOut"></typeparam>
public class ExpressionGenericMapper<TIn,TOut>
{
private static Func<TIn, TOut> _Func = null;
static ExpressionGenericMapper()
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties())
{
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);//TOut.age = TIn.age赋值, 映射表达式
memberBindingList.Add(memberBinding);
}
foreach (var item in typeof(TOut).GetFields())
{
MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);//TOut.age = TIn.age赋值
memberBindingList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());//初始化表达式
Expression<Func<TIn, TOut>> expression = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] {
parameterExpression
});
_Func = expression.Compile();
}
public static TOut Trans(TIn t)
{
return _Func(t);
}
}
}
分析
它是有泛型机制和static组合实现的泛型缓存机制,其中静态变量_Func的生命周期保证实现缓存机制。
而泛型可以保证缓存多个不同类。原理为调用该类的泛型参数不同时,会生成不同的实例。
一个类的静态构造函数只会调用一次,但输入的泛型不同,.net认为是不同的类,所以输入的泛型不同会调用多次静态构造函数,会有多个_Func被缓存。
应用场景
用EF创建的数据库实体类,在查询数据时我们一般不会直接返回EF映射的实体类,我们一般会在创建一个字段内容相同的数据返回类。此时就可以用上述方法了。