Optimization 如何优化LINQ表达式?
在使用.NET3.5构建的项目中,我使用LINQ表达式在运行时动态生成代码。LINQ表达式是使用Compile方法编译的,并存储起来作为LINQto对象的谓词使用 这些表达式有时相当复杂,难以调试 下面是通过VisualStudio中的调试器可视化工具查看的表达式示例 {请求 =>(调用(工作信封头) =>(workEnvelopeHead.Method=value(Wombl.Scenarios.CannedResponses+c_DisplayClass58).pipeline), 请求。工作信封。标题) 和调用(body=> 调用(值(Wombl.Scenarios.CannedResponses+c_DisplayClass78).isMatch, body.SingleOrDefault()),Convert(request.WorkEnvelope.body.Any))} 我希望能够优化上述表达式,以便将Optimization 如何优化LINQ表达式?,optimization,linq-expressions,Optimization,Linq Expressions,在使用.NET3.5构建的项目中,我使用LINQ表达式在运行时动态生成代码。LINQ表达式是使用Compile方法编译的,并存储起来作为LINQto对象的谓词使用 这些表达式有时相当复杂,难以调试 下面是通过VisualStudio中的调试器可视化工具查看的表达式示例 {请求 =>(调用(工作信封头) =>(workEnvelopeHead.Method=value(Wombl.Scenarios.CannedResponses+c_DisplayClass58).pipeline), 请求。工
值(Wombl.Scenarios.CannedResponses+c_udisplayClass58).管道表达式替换为变量值的常量
在这种特殊情况下,值(Wombl.Scenarios.CannedResponses+c__DisplayClass58)。管道是lambda中对父范围中变量的引用。比如:
var pipeline = "[My variable's value here]";
// My lambda expression here, which references pipeline
// Func<RequestType, bool> predicate = request => ........ workEnvelopeHead.Method == pipeline ..........
var pipeline=“[My variable's value here]”;
//这里是lambda表达式,它引用管道
//Func谓词=请求=>。。。。。。。。workEnvelopeHead.Method==管道。。。。。。。。。。
优化后的原始表达式应该如下所示:
{request=>(调用(workEnvelopeHead=>
(workEnvelopeHead.Method=“[My variable's value here]”,
request.WorkEnvelope.Head)和Invoke(body=>>Invoke(value(Wombl.Scenarios.CannedResponses+c_udisplayClass78).isMatch,
body.SingleOrDefault()),Convert(request.WorkEnvelope.body.Any))}
在编译之前,我如何在运行时对LINQ表达式进行这样的优化?因此,我继续编写了一个表达式访问者,用实际值替换变量引用。这毕竟不难做到
用法:
var simplifiedExpression = ExpressionOptimizer.Simplify(complexExpression);
班级:
它继承自ExpressionVisitor,它来自上的代码示例,因为在.NET 3.0中它是内部的。在.NET 4.0中,该类是公共的,但可能需要对此类进行一些更改
public sealed class ExpressionOptimizer : ExpressionVisitor
{
private ExpressionOptimizer()
{
}
#region Methods
public static Expression<TDelegate> Simplify<TDelegate>(Expression<TDelegate> expression)
{
return expression == null
? null
: (Expression<TDelegate>) new ExpressionOptimizer().Visit(expression);
}
private static bool IsPrimitive(Type type)
{
return type.IsPrimitive
|| type.IsEnum
|| type == typeof (string)
|| type == typeof (DateTime)
|| type == typeof (TimeSpan)
|| type == typeof (DateTimeOffset)
|| type == typeof (Decimal)
|| typeof(Delegate).IsAssignableFrom(type);
}
protected override Expression VisitMemberAccess(MemberExpression memberExpression)
{
var constantExpression = memberExpression.Expression as ConstantExpression;
if (constantExpression == null || !IsPrimitive(memberExpression.Type))
return base.VisitMemberAccess(memberExpression);
// Replace the MemberExpression with a ConstantExpression
var constantValue = constantExpression.Value;
var propertyInfo = memberExpression.Member as PropertyInfo;
var value = propertyInfo == null
? ((FieldInfo) memberExpression.Member).GetValue(constantValue)
: propertyInfo.GetValue(constantValue, null);
return Expression.Constant(value);
}
#endregion
}
公共密封类ExpressionOptimizer:ExpressionVisitor
{
private ExpressionOptimizer()
{
}
#区域方法
公共静态表达式简化(表达式)
{
返回表达式==null
无效的
:(表达式)新建表达式优化工具()。访问(表达式);
}
专用静态bool IsPrimitive(类型)
{
返回类型.IsPrimitive
||伊塞努姆型
||type==typeof(字符串)
||type==typeof(日期时间)
||类型==类型(时间跨度)
||type==typeof(DateTimeOffset)
||类型==typeof(十进制)
||typeof(委托)。IsAssignableFrom(类型);
}
受保护的重写表达式VisitMemberAccess(MemberExpression MemberExpression)
{
var constantExpression=memberExpression。表达式为constantExpression;
if(constantExpression==null | |!IsPrimitive(memberExpression.Type))
返回base.VisitMemberAccess(memberExpression);
//用常量表达式替换MemberExpression
var constantValue=ConstantPression.Value;
var propertyInfo=memberExpression.Member作为propertyInfo;
变量值=propertyInfo==null
?((FieldInfo)memberExpression.Member).GetValue(constantValue)
:propertyInfo.GetValue(constantValue,null);
返回表达式。常量(值);
}
#端区
}
你说的是“优化”但您给出的唯一问题是调试。可能有些事情会使调试变得更容易,但会影响性能,反之亦然。您能否澄清哪一个目标对您很重要?通过优化,我的意思是以更简单的形式重写表达式树,这将提高性能并使表达式树更易于阅读。因此,虽然提高运行时性能和可读性都是目标,但表达式的可读性更为重要。表达式在运行时写入日志以帮助调试。我正在考虑编写ExpressionVisitor来重写表达式树,将变量引用替换为具有变量值的常量可以。但是,我希望其他人也尝试过类似的方法,并且可能解决方案已经存在。是的,访问者可能就是您所需要的。表达式树在很多方面都很好,但像这样操纵它们是一件痛苦的事:(