扩展方法上的Lambda表达式仅从对象获取属性

时间:2016-02-04 10:28:40

标签: c# .net lambda

我正在编写一个小的验证流畅API,用于验证我正在使用的命令:

/* Test for GCC > 4.6 */
#if !(__GNUC__ > 3 && __GNUC_MINOR__ > 6)
#error gcc above version 4.6 required!
#endif

实际上,verify方法将lambda表达式的值(在本例中是从Validator.Candidate(foo).Verify(x => x.Name).IsNotNull(); 属性中提取的字符串)传递给一组扩展方法,例如foo.Name,{{1}然后,扩展方法可以在需要时引发错误,等等。

API中使用的基础类和扩展方法是:

IsNotNull()

上面显示的IsGreaterThan(10)扩展程序并不重要,与手头的问题无关。

问题是在public static class Validator { public static ValidationCandidate<T> Candidate<T>(T candidate) { return new ValidationCandidate<T>(candidate); } } public class ValidationCandidate<T> : IValidatorCandidate<T> { public ValidationCandidate(T candidate) { Object = candidate; } public T Object { get; private set; } } public class ValidatorProperty<TCommand, TProperty> : IValidatorProperty { public static ValidatorProperty<TCommand, TProperty> Verify<TCommand, TProperty>(this IValidatorCandidate<TCommand> candidate, Expression<Func<TCommand>> func) { return new ValidatorProperty<TCommand, TProperty>(candidate, func.Invoke(candidate.Object), name); } } public class ValidatorProperty<TCommand, TProperty> : IValidatorProperty { public ValidatorProperty(IValidatorCandidate<TCommand> candidate, TProperty value, string name) { } public TProperty Value { get; private set; } public IValidatorCandidate<TCommand> Candidate { get; private set; } } 方法中我传递一个lambda来选择IsNotNull()中使用的对象的属性。

我希望能够做的是限制Verify()中使用的lambda只允许传入候选对象的属性,即候选对象被定义为:

Candidate()

我希望能够做到:

Verify()

但不是:

public Foo() {
   string Name { get; set; }
}

目前,上述两个用法都将编译。我认为这是因为我在Validator.Object(instanceOfFoo).Verify(x => x.Name)..... 中为lamda写了不正确的签名,因为我想做什么,不知道怎么写它来做我想做的事!

lambda需要编写,例如,如果尝试将某些内容传递给Validator.Object(instanceOfFoo).Verify(x => "Hello").... ,而不是Foo的属性(或者任何对象被用作候选对象),则需要编写错误被抛出。我不想在运行时进行检查。

1 个答案:

答案 0 :(得分:1)

无法在C#中表达该约束,因此编译器无法在编译时检查它。

但是,您可以在运行时使用静态代码分析来捕获它。最简单的方法是使用Roslyn:https://msdn.microsoft.com/en-us/magazine/dn879356.aspx

这样,您可以立即向开发人员提供反馈,并在构建时捕获任何错误。