从 Func转换成员访问函数到 Func

发布于 2025-01-04 12:00:47 字数 1131 浏览 1 评论 0原文

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

我正在做的是通过 BaseMap< 进行签入T> : 类映射< 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\n参数”名称:表达式”。

我如何创建和转换 MemberExpression 或任何类似的可以工作的东西?

I'm trying to creating a dynamic base mapping with fluent nhibernate.

What I'm doing is checking in by a BaseMap< T > : ClassMap< T > if for example:
(typeof(ICategorizedEntity).IsAssignableFrom(typeof(T)))

If so, I wanna map a property named "Category" which belongs to ICategorizedEntity's interface, but the Map(Func) function only accepts T's properties, so I tried guessing a little with linq and came up with this:

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

Which doesn't work, because deep inside the 'Map' function it checks the following:

   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");

And I get the "Not a member access\r\nParameter name: expression".

How can I create and cast a MemberExpression or anything similar which will work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

臻嫒无言 2025-01-11 12:00:47

Func 表示接受 DerivedFromT 参数的方法。 Func 表示接受 T 参数的方法。通过 C# 4 中引入的 委托变体,您可以强制转换 Func< ;T,object>Func,但不是相反(如您所请求)。

想想这意味着什么:

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 匹配,而 Promote 方法与委托 Func匹配委托Func

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

我们可以将 Greet 转换为 Func;如果我们可以问候一个Person,那么我们也可以问候一个Student(他保证是Person的一种特殊形式)。

Func<Student, object> greetStudent = greetPerson;

但是,我们无法将 Promote 转换为 Func;尽管我们可以晋升学生,但我们一般不能晋升任何,除非他/她恰好是学生

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

如果我们知道我们的 Person 是一名学生,我们可以通过强制转换来表明这一点:

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

Func<DerivedFromT,object> represents a method that accepts a DerivedFromT parameter. Func<T,object> represents a method that accepts a T parameter. Through delegate variance introduced in C# 4, you can cast Func<T,object> to Func<DerivedFromT,object>, but not the other way round (as you’re requesting).

Think about what this means:

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

In this case, the Greet method matches the delegate Func<Person,object>, whilst the Promote method matches the delegate Func<Student,object>.

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

We can cast Greet to Func<Student,object>; if we can greet a Person, then we can also greet a Student (who is guaranteed to be a specialized form of Person).

Func<Student, object> greetStudent = greetPerson;

However, we cannot cast Promote to Func<Person,object>; although we can promote a Student, we cannot promote any Person in general, unless he/she happens to be a Student.

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

If we know that our Person is a student, we can indicate this by casting it:

Func<Person, object> promotePerson =
    personWhoIsActuallyStudent => promoteStudent((Student)personWhoIsActuallyStudent);
罗罗贝儿 2025-01-11 12:00:47

谢谢道格拉斯,你引导我找到了正确(简单)的答案。

我为了找到它走得太远了。

良好的旧转换(在 lambda 表达式内)成功了:

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

Thanks Douglas, you lead me to the right (simple) answer.

I went too far trying to find it..

Good old conversion (inside the lambda expression) did the trick:

   Map(x => ((ICategorizedEntity)x).Category);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文