我正在编写一个小的验证流畅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的属性(或者任何对象被用作候选对象),则需要编写错误被抛出。我不想在运行时进行检查。
答案 0 :(得分:1)
无法在C#中表达该约束,因此编译器无法在编译时检查它。
但是,您可以在运行时使用静态代码分析来捕获它。最简单的方法是使用Roslyn:https://msdn.microsoft.com/en-us/magazine/dn879356.aspx
这样,您可以立即向开发人员提供反馈,并在构建时捕获任何错误。