Лямбда-выражение: приведение параметра к базовому типу - PullRequest
7 голосов
/ 03 мая 2011

Я бы хотел "обернуть" функцию получения для определенного свойства, которое является частью определенного типа. У меня есть абстрактный класс, определенный следующим образом:

public abstract class MyAbstractClass<T> where T : MyType
{
    // ...
}

Хорошо, предположим, у меня есть конкретный класс, подобный следующему:

public abstract class MyConcreteClass : MyAbstractClass<MyConcreteType>
{
    // ...
}

А теперь вспомогательный метод, который должен возвращать оболочку для метода get:

private Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
{
    var instanceType = Expression.Parameter(property.DeclaringType, "i");

    // Taking getter's "body".
    var getterBody = Expression.Property(instanceType, property);

    // Cast to a generic Object.
    var body = Expression.TypeAs(getterBody, typeof(Object));

    // Build the expression.
    var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(body, instanceType);
    return exp.Compile();
}

Как и ожидалось, я получаю следующее исключение:

ParameterExpression типа 'MyConcreteClass' нельзя использовать для Параметр делегата типа «MyAbstractClass ».

Есть ли способ "форсировать" этот тип литья? Заранее спасибо.

Ответы [ 2 ]

12 голосов
/ 04 мая 2011

Если я правильно понимаю ваш вопрос, вы хотите создать лямбда-выражение вроде этого:

Func<MyAbstractClass<T>, Object> f = i => ((MyConcreteClass)i).SomeProperty;

За исключением того, что вы хотите указать, какое свойство является SomeProperty в качестве параметра.Что ж, если вы хотите построить это выражение программно, вы должны сделать то же самое: иметь параметр выражения i (типа MyAbstractClass<T>), привести его к MyConcreteClass и затем получить доступ к свойству SomeProperty этого.

public Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
{
    var parameter = Expression.Parameter(typeof(MyAbstractClass<T>), "i");

    var cast = Expression.TypeAs(parameter, property.DeclaringType);

    var getterBody = Expression.Property(cast, property);

    var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(
        getterBody, parameter);

    return exp.Compile();
}

Сказав это, я абсолютно не знаю, зачем вам это делать, поэтому вам лучше быть уверенным, что это именно то, что вы хотите сделать, и что нет лучшего способа сделать то, чтоВы действительно хотите сделать.

0 голосов
/ 03 мая 2011

Разве вы не должны создавать тип экземпляра из универсального типа?

var genericType = typeof(MyAbstractClass<>).MakeGenericType(property.DeclaringType);
var instanceType = Expression.Parameter(genericType , "i");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...