Optimization 如何优化LINQ表达式?

Optimization 如何优化LINQ表达式?,optimization,linq-expressions,Optimization,Linq Expressions,在使用.NET3.5构建的项目中,我使用LINQ表达式在运行时动态生成代码。LINQ表达式是使用Compile方法编译的,并存储起来作为LINQto对象的谓词使用 这些表达式有时相当复杂,难以调试 下面是通过VisualStudio中的调试器可视化工具查看的表达式示例 {请求 =>(调用(工作信封头) =>(workEnvelopeHead.Method=value(Wombl.Scenarios.CannedResponses+c_DisplayClass58).pipeline), 请求。工

在使用.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))}

我希望能够优化上述表达式,以便将
值(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来重写表达式树,将变量引用替换为具有变量值的常量可以。但是,我希望其他人也尝试过类似的方法,并且可能解决方案已经存在。是的,访问者可能就是您所需要的。表达式树在很多方面都很好,但像这样操纵它们是一件痛苦的事:(