强制“ Expression <Func <TInstance,TProp >>”的主体为“ MemberExpression”

时间:2019-11-18 11:57:49

标签: c# generics reflection expression

public void GiveMeAProp(Expression<Func<TInstance,TProp>> prop)

通常用作说“请给我一个属性选择器”的标准方式。但是有很多东西可以满足这个签名,但实际上不是“真实”属性。例如以下所有内容均会编译。

GiveMeAProp(x => Method());
GiveMeAProp((x) => localVariable);
GiveMeAProp(x => x);
GiveMeAProp(x => (Type)x);
GiveMeAProp((x) => !x.BooleanProp);

我当然可以简单地声明我的方法采用MemberExpression,但是随后我失去了表达式的严格类型,特别是失去了编写代码的能力:

public void SetThisProp(Expression<Func<TInstance,TProp>> prop, TProp value)

我可以进行运行时检查,以确保最终得到的表达式的Body为MemberExpression,但是如果我可以让类型系统为我强制执行该表达式,那真的很好吗?在我的用例中,没有其他类型的Expression<T>实际上是有效的参数。

问题:无论如何,我是否可以强制执行静态,即参数代表MemberExpression,而返回参数类型{{1 }}?

1 个答案:

答案 0 :(得分:1)

  

无论如何,我是否可以静态地强制参数表示MemberExpression并返回类型T?

不,目前不在C#中。

很难证明是否定的,但是我认为从所有遵循您引用的模式的各种库中可以很清楚地看出这是最佳方法。如果有更好的方法,我认为它现在会流行很多。

对于eaxmple来说,"OrderBy" method in Linq是一个非常经典的示例,如您在此处所做的那样,库以类型安全的方式请求属性,它们并没有避免您引用的相同陷阱:< / p>

None

以下内容将编译,但在运行时将失败:

def my_function(grade=None):
    if grade is None:
        grade = "other"
    return grade.lower()

我认为,只要用户通过public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector); var studentsOrderByRank = students.OrderBy(w => w.Rank); (实际上不是属性访问),只要您的库在运行时给出明确的错误消息,这就是您的最佳选择。

另请参阅this answer,以获取图书馆中重用这些表达式的最佳实践。