将成员访问函数从Func <derivedfromt,object>转换为Func <t,object> </t,object> </derivedfromt,object>

时间:2012-02-10 23:06:18

标签: c# linq casting expression fluent-nhibernate-mapping

我正在尝试使用流畅的nhibernate创建动态基本映射。

我正在做的是通过BaseMap&lt; T> :ClassMap&lt; T>如果例如:                 (typeof运算(ICategorizedEntity).IsAssignableFrom(typeof运算(T)))

如果是这样,我想映射名为“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);

哪个不起作用,因为在'Map'函数内部检查以下内容:

   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 \ nParameter name:expression”。

如何创建和转换MemberExpression或其他类似的东西?

2 个答案:

答案 0 :(得分:2)

Func<DerivedFromT,object>表示接受DerivedFromT参数的方法。 Func<T,object>表示接受T参数的方法。通过C#4中引入的delegate variance,您可以将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);

答案 1 :(得分:2)

感谢道格拉斯,你引导我做出正确的(简单的)答案。

我试图找到它太过分了..

良好的旧转换(在lambda表达式中)做了诀窍:

   Map(x => ((ICategorizedEntity)x).Category);