ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.Net Expression表达式目录树(自己动态创建表达式目录树)

2020-07-29 12:32:58  阅读:479  来源: 互联网

标签:动态创建 else item typeof PropertyType var Expression 目录 表达式


一直以来自己从数据库取数据,都是遍历SqlDataReader。通过SqlDataReader的string索引器获取数据。

后来自己研究反射,可以动态的将SqlDataReader的数据赋值给泛型T。省了不少收写代码的工作。但是随着业务量的增加,一直使用反射就会有性能和资源的损耗。为了解决这个问题。就想到了缓存+反射+表达式目录树。把已经赋值过的泛型T,缓存起来,下次找缓存,如果有赋值过具体T类型,就直接取缓存的目录树,然后Compile().Invoke()。这就解决了性能损耗和代码量的问题。

这个是以前的方法,避免不了性能损耗问题

public List<T> FindAll<T>() where T : BaseModel
{
Type type = typeof(T);
List<T> list = new List<T>();
//var Parameter = new SqlParameter("@Id", Id);
using (SqlConnection connection = new SqlConnection(StaticField.Connection))
{
SqlCommand command = new SqlCommand(Cache<T>.DeleteSql, connection);
//command.Parameters.Add(Parameter);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
var t = Activator.CreateInstance(type) as T;
foreach (var item in type.GetProperties())
{
item.SetValue(item.Name, reader[$"{item.Name }"]==DBNull.Value?null: reader[$"{item.Name }"]);
}
list.Add(t);
}
connection.Close();
return list;
}
}

先解释一下什么是表达式目录树,其实就是把表达式理解成一个树。组装的时候,一个叶一个叶的取组装。拆解的时候一个一个的拆。(从右往左拆或者组装)就比如说表达式

x.name==5&&x.Age>3。可以拆成x/、name、&&、 x 、age 。这些具体的元素都能找到表达式目录树里面对应的表示方法。具体的方法你们可以研究一下Expression类。里面有方法、属性、字段等等的组装方法。拿上面那个做个例子:

 ParameterExpression parameter = Expression.Parameter(typeof(具体类型), "P");这个P就是给这个委托给起了个别名(统一了一个名字)

x.name这个name是个属性。所以就添加p的name属性

PropertyInfo Info = typeof(具体类型).GetProperty("name");
MemberExpression member = Expression.Property(parameter, Info);//把p和name拼起来就成了p.name.
表达式目录树里面有表示==、&&、>、乘除等等等。反正都能拼接起来。很多方法,我研究了很长时间,才研究了几个方法。你们自己探究

 

这个是使用表达式目录树的方式。自己在添加一个缓存,把已经通过目录树赋值过的缓存起来,下次来的时候,直接用。审了不少性能问题

public TOut ExpressionConvertToModel<TOut>(SqlDataReader tin)
{
ParameterExpression parameter = Expression.Parameter(typeof(SqlDataReader), "P");
List<MemberBinding> list = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties())
{
string Info = tin[item.Name].ToString();
if (Info != null)
{

//PropertyInfo Infos = tin.GetType().GetProperty("item_get");索引器就是调用对象属性的item_get方法。
var In = tin.GetType().GetProperties().Where(m => m.GetIndexParameters().Length > 0).ToArray()[1];//获取string索引器
//MemberExpression member = Expression.Property(parameter, In);//p.属性名
//下一步就是拼接这个SqlDataReader[]
var methodCall = Expression.Call(parameter,In.GetMethod, Expression.Constant(item.Name));//call就是调用方法,都一个是p然后是p.Get_item()这个表示索引器的get方法,最后一个是参数

MethodInfo containsMethod = typeof(object).GetMethod("ToString");
if (typeof(string) == item.PropertyType)
{
containsMethod = typeof(object).GetMethod("ToString");//using System.Reflection;ToString方法
}
else if (typeof(bool) == item.PropertyType)
{
//下面自己去扩展
}
else if (typeof(byte) == item.PropertyType)
{

}
else if (typeof(char) == item.PropertyType)
{

}
else if (typeof(decimal) == item.PropertyType)
{

}
else if (typeof(double) == item.PropertyType)
{

}
else if (typeof(float) == item.PropertyType)
{

}
else if (typeof(long) == item.PropertyType)
{

}
else if (typeof(sbyte) == item.PropertyType)
{

}
else if (typeof(short) == item.PropertyType)
{

}
else if (typeof(uint) == item.PropertyType)
{

}
containsMethod = typeof(object).GetMethod("ToString");//T获取object的Tostring方法
var methodCal2 = Expression.Call(methodCall, containsMethod);//调用Tostring方法
//var methodCal2 = Expression.ArrayIndex(methodCall, Expression.Constant(item.Name));
//var methodCall = Expression.Call(parameter,In.GetMethod ?? throw new InvalidOperationException(), Expression.Constant(item.Name));
MemberBinding member1 = Expression.Bind(item, methodCal2);//p.属性名=属性名
list.Add(member1);
}
}
MemberInitExpression memberInit = Expression.MemberInit(Expression.New(typeof(TOut)), list.ToArray());
Expression<Func<SqlDataReader, TOut>> expression = Expression.Lambda<Func<SqlDataReader, TOut>>(memberInit, new ParameterExpression[] { parameter });
return expression.Compile().Invoke(tin);
}

标签:动态创建,else,item,typeof,PropertyType,var,Expression,目录,表达式
来源: https://www.cnblogs.com/haunge/p/13396400.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有