문제

이전에 lamdas를 기반으로 C# 표현식을 사용한 적이 있지만 직접 작성해 본 경험은 없습니다.주어진 Expression<Func<SomeType, bool>> originalPredicate, 나는 Expression<Func<OtherType, bool>> translatedPredicate.

이 경우 SomeType과 OtherType은 동일한 필드를 가지지만 서로 관련이 없습니다(상속이 없고 공통 인터페이스를 기반으로 하지 않음).

배경:LINQ to SQL을 기반으로 한 리포지토리 구현이 있습니다.POCO에 모델을 유지하기 위해 LINQ to SQL 엔터티를 모델 엔터티에 투영합니다.표현식을 사양의 형태로 저장소에 전달하고 싶지만 모델 엔터티를 기반으로 해야 합니다.하지만 해당 표현식을 데이터 컨텍스트에 전달할 수는 없습니다. 왜냐하면 LINQ to SQL 엔터티를 기반으로 하는 표현식이 필요하기 때문입니다.

도움이 되었습니까?

해결책

와 함께 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 });
    }
}

그러나 이는 제공업체마다 다르게 지원된다는 점에 유의하세요.예를 들어 LINQ-to-SQL이 좋아하더라도 EF는 이를 좋아하지 않을 수 있습니다.

다른 옵션은 표현식 트리를 다시 작성하는 것입니다. 완전히, 리플렉션을 사용하여 해당 멤버를 찾습니다.훨씬 더 복잡합니다.

다른 팁

내가 찾은 또 다른 방법이 있는데, 여기에는 원래 대리자를 래핑하는 것도 포함됩니다.

Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
{
    Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
    return g.Compile();
}

번역을 수행하는 암시적인 방법은 없습니다.인수 유형에서 새 유형을 생성하는 람다 내에 기존 대리자를 래핑해야 합니다.

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

어디 OtherTypeFromSomeType 생성합니다 OtherType 인스턴스의 SomeType 논쟁.

나는 당신과 같은 문제가 있었고 EF로 다음과 같이 해결했습니다.

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

Entity Framework는 올바른 SQL 명령을 작성하는 방법을 알고 있습니다.표현식을 변환하는 것은 훨씬 더 복잡합니다. 왜냐하면 표현식은 불변으로 만들어졌고 뭔가 잘못하면 원하지 않는 런타임 효과를 일으킬 수 있고 적어도 제 경우에는 필요하지 않기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top