重用lambda表达式

今天我有这个重复的代码:

 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,
        };
    }
 }

第一种方法是可重复使用的投影表达式,我使用这种方式:

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

当我不处理集合时使用第二种方法,但只需要一个需要序列化的项目,如下所示:

    MyProjectionExpressions.LogSelector(someLog);

我尝试重复使用代码,如下所示:

 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,
        };
    }
 }

但是之后,我有了“Linq-To-Entities vs Linq-To-Objects”的问题,那就是:我必须像这样重用我的投影表达式:

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

由于MyProjectionExpressions.LogSelector()现在包含(使用)Linq-To-Entities无法识别的方法:

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



问题是,最后:
我怎样才能以Linq-To-Entities继续工作的方式重用lamba表达式?

这个lambda表达式:

        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);
    }
 }

不是用编译的方法来实现表达式,而是用表达式来实现编译的方法:

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);
    }
}

请注意,为避免每次需要使用时不断重新编译表达式,可以缓存编译后的表达式并重新使用它。

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

上一篇: Reusing lambda expression

下一篇: Semantics of Captured Variables