C # كيفية تحويل التعبير <ظائفها > إلى التعبير <ظائفها <أخرىالنوع >>

StackOverflow https://stackoverflow.com/questions/654153

سؤال

ولقد استخدمت C # تعبيرات قبل على أساس lamdas، ولكن ليست لدي خبرة يؤلف لهم باليد. إعطاء Expression<Func<SomeType, bool>> originalPredicate، أريد أن خلق Expression<Func<OtherType, bool>> translatedPredicate.

في هذه الحالة SomeType وأخرىالنوع لها نفس المجالات، ولكنها ليست ذات الصلة (أي الميراث، وليس بناء على واجهة مشتركة).

والخلفية: لدي تنفيذ مستودع بناء على LINQ إلى SQL. I إبراز LINQ إلى SQL الكيانات إلى كيانات نموذج بلدي، للحفاظ على طراز بي في POCO. أريد أن تمرير تعبيرات إلى المخزون (كشكل من أشكال المواصفات) ولكن ينبغي أن يستند إلى كيانات نموذج. لكنني لا يمكن أن تمر تلك التعبيرات إلى سياق البيانات، لأنها تتوقع التعبيرات على أساس LINQ إلى 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 });
    }
}

ملحوظة إلا أن هذا سوف تكون معتمدة بشكل مختلف من قبل مقدمي مختلفة. EF قد لا ترغب في ذلك، على سبيل المثال، حتى لو-LINQ إلى SQL يفعل.

والخيار الآخر هو لإعادة بناء شجرة التعبير على تماما ، أو باستخدام الانعكاس للعثور على أعضاء المقابلة. أكثر تعقيدا.

نصائح أخرى

وهناك طريقة واحدة أخرى وجدت، التي تضم ايضا التفاف مندوب الأصلي.

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>>

والكيان الإطار يعرف كيفية بناء أمر SQL الصحيح. تحويل التعبير هو أكثر تعقيدا بكثير، لأنها بنيت لتكون غير قابل للتغيير، ويمكن أن تتسبب في آثار وقت التشغيل غير مرغوب فيها إذا كنت تفعل شيئا خاطئا، و، في حالتي على الأقل، ليست هناك حاجة إليها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top