Reusing lambda expression

Today I have this repeated code:

 public class MyProjectionExpressions
 {
    public static Expression<Func<Log, dynamic>> LogSelector()
    {
        return log => new
        {
            logId = log.LogId,
            message = log.Message,
        };
    }

    public static dynamic LogSelector(Log log)
    {
        return new
        {
            logId = log.LogId,
            message = log.Message,
        };
    }
 }

The first method is a reusable projection expression, which I use like this:

    db.Logs.Select(MyProjectionExpressions.LogSelector());

The second method is used when I'm not dealing with collections, but just one item that needs to be serialized, like this:

    MyProjectionExpressions.LogSelector(someLog);

I tried reusing code, like this:

 public class MyProjectionExpressions
 {
    public static Expression<Func<Log, dynamic>> LogSelector()
    {
        return log => MyProjectionExpressions.LogSelector(log);
    }

    public static dynamic LogSelector(Log log)
    {
        return new
        {
            logId = log.LogId,
            message = log.Message,
        };
    }
 }

But then, I had the "Linq-To-Entities vs Linq-To-Objects" problem, that is: I would have to reuse my projection expression like this:

    db.Logs.ToList().Select(MyProjectionExpressions.LogSelector());

Because MyProjectionExpressions.LogSelector() now contains (uses) a method that is not recognized by Linq-To-Entities:

    LINQ to Entities does not recognize the method 'MyProjectionExpressions.LogSelector()'



Question is, finally:
how can I reuse the lamba expression in a way that Linq-To-Entities continues to work?

This lambda expression:

        log => new
        {
            logId = log.LogId,
            message = log.Message,
        };

你可以这样做:

 public class MyProjectionExpressions
 {
    public static Expression<Func<Log, dynamic>> LogSelector()
    {
        return log => new
        {
            logId = log.LogId,
            message = log.Message,
        };
    }

    //Get the expression as a Func<Log, dynamic>, then apply it
    //to your log object.
    private static Func<Log, dynamic> impl = LogSelector().Compile();

    public static dynamic LogSelector(Log log)
    {
        return impl(log);
    }
 }

Rather than implementing the expression in terms of the compiled method, implement the complied method in terms of the expression:

public class MyProjectionExpressions
{
    public static Expression<Func<Log, dynamic>> LogSelector()
    {
        return log => new
        {
            logId = log.LogId,
            message = log.Message,
        };
    }
    private static Lazy<Func<Log, dynamic>> func;
    static MyProjectionExpressions()
    {
        func = new Lazy<Func<Log, dynamic>>(() => LogSelector().Compile());
    }
    public static dynamic LogSelector(Log log)
    {
        return func.Value(log);
    }
}

Note that to avoid constantly re-compling the expression every time it needs to be used you can cache the compiled expression and re-use it.

链接地址: http://www.djcxy.com/p/51552.html

上一篇: 当一个变量关闭两次时,它存储在哪里?

下一篇: 重用lambda表达式