Приведение функции доступа к члену из Funcв Func - PullRequest
2 голосов
/ 11 февраля 2012

Я пытаюсь создать динамическое базовое отображение с помощью свободного nhibernate.

Что я делаю, так это проверяю BaseMap : ClassMap , если, например: (TypeOf (ICategorizedEntity) .IsAssignableFrom (TypeOf (Т))) * * 1003

Если это так, я хочу отобразить свойство с именем "Category", которое принадлежит интерфейсу ICategorizedEntity, но функция Map (Func) принимает только свойства T, поэтому я попытался немного угадать с linq и придумал следующее:

   Expression<Func<ICategorizedEntity, object>> exp = x => x.Category;
   var parameter = Expression.Parameter(typeof (T));
   var lmd = Expression.Lambda<Func<T, object>>(exp, parameter);
   Map(lmd);

Что не работает, потому что глубоко внутри функции «Карта» он проверяет следующее:

   MemberExpression memberExpression = (MemberExpression) null;
   if (expression.NodeType == ExpressionType.Convert)
       memberExpression = ((UnaryExpression) expression).Operand as MemberExpression;
   else if (expression.NodeType == ExpressionType.MemberAccess)
       memberExpression = expression as MemberExpression;
   if (enforceCheck && memberExpression == null)
       throw new ArgumentException("Not a member access", "expression");

И я получаю «Не член доступа \ r \ nПараметр имя: выражение».

Как я могу создать и привести выражение MemberExpression или что-нибудь подобное, что будет работать?

Ответы [ 2 ]

2 голосов
/ 11 февраля 2012

Спасибо, Дуглас, вы привели меня к правильному (простому) ответу.

Я зашел слишком далеко, пытаясь найти его ..

Старое доброе преобразование (внутри лямбда-выражения) добилось цели:

   Map(x => ((ICategorizedEntity)x).Category);
2 голосов
/ 11 февраля 2012

Func<DerivedFromT,object> представляет метод, который принимает параметр DerivedFromT. Func<T,object> представляет метод, который принимает параметр T. Через дисперсию делегата , представленную в C # 4, вы можете привести Func<T,object> к Func<DerivedFromT,object>, но не наоборот (как вы запрашиваете).

Подумайте, что это значит:

public class Person { }

public class Student : Person { }

public static class School
{
    public static object Greet(Person person)
    {
        return null; 
    }

    public static object Promote(Student student)
    { 
        return null; 
    }
}

В этом случае метод Greet соответствует делегату Func<Person,object>, а метод Promote соответствует делегату Func<Student,object>.

Func<Person, object> greetPerson = School.Greet;
Func<Student, object> promoteStudent = School.Promote;

Мы можем разыграть Greet до Func<Student,object>; если мы можем приветствовать Person, то мы также можем приветствовать Student (который гарантированно будет специализированной формой Person).

Func<Student, object> greetStudent = greetPerson;

Однако мы не можем разыграть Promote до Func<Person,object>; хотя мы можем рекламировать Student, мы не можем рекламировать вообще Person, если только он / она не является Student.

Func<Person, object> promotePerson = promoteStudent;   // Will not compile.

Если мы знаем, что наш Person - студент, мы можем указать это, применив его:

Func<Person, object> promotePerson =
    personWhoIsActuallyStudent => promoteStudent((Student)personWhoIsActuallyStudent);
...