15

我之前使用过基于 lamdas 的 C# 表达式,但我没有手工编写它们的经验。给定一个Expression<Func<SomeType, bool>> originalPredicate,我想创建一个Expression<Func<OtherType, bool>> translatedPredicate.

在这种情况下 SomeType 和 OtherType 具有相同的字段,但它们不相关(没有继承并且不基于公共接口)。

背景:我有一个基于 LINQ to SQL 的存储库实现。我将 LINQ to SQL 实体投影到我的模型实体中,以将我的模型保存在 POCO 中。我想将表达式传递给存储库(作为规范的一种形式),但它们应该基于模型实体。但我不能将这些表达式传递给数据上下文,因为它需要基于 LINQ to SQL 实体的表达式。

4

4 回答 4

22

使用Expression,最简单的方法是使用转换表达式

class Foo {
    public int Value { get; set; }
}
class Bar {
    public int Value { get; set; }
}
static class Program {
    static void Main() {
        Expression<Func<Foo, bool>> predicate =
            x => x.Value % 2 == 0;
        Expression<Func<Bar, Foo>> convert =
            bar => new Foo { Value = bar.Value };

        var param = Expression.Parameter(typeof(Bar), "bar");
        var body = Expression.Invoke(predicate,
              Expression.Invoke(convert, param));
        var lambda = Expression.Lambda<Func<Bar, bool>>(body, param);

        // test with LINQ-to-Objects for simplicity
        var func = lambda.Compile();
        bool withOdd = func(new Bar { Value = 7 }),
             withEven = func(new Bar { Value = 12 });
    }
}

但是请注意,不同的提供者将对此提供不同的支持。例如,EF 可能不喜欢它,即使 LINQ-to-SQL 喜欢。

另一种选择是完全重建表达式树,使用反射找到相应的成员。复杂得多。

于 2009-03-17T13:51:32.420 回答
3

我发现了另一种方法,它还包括包装您的原始委托。

Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
{
    Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
    return g.Compile();
}
于 2012-04-24T14:12:05.200 回答
2

没有隐含的方式来进行翻译。您必须将现有委托包装在从参数类型创建新类型的 lambda 中:

var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))

Where从参数OtherTypeFromSomeType创建OtherType实例。SomeType

于 2009-03-17T13:08:33.927 回答
0

我和你有同样的问题,我用 EF 解决了这个问题:

var viewModeValue = dbContext.Model.Select(m => new ViewModel{Field = m.Field}).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>

Entity Framework 知道如何构建正确的 sql 命令。转换表达式要复杂得多,因为它是不可变的,如果你做错了什么,可能会导致不希望的运行时效果,至少在我的情况下,它是不需要的。

于 2017-05-09T22:36:45.523 回答