扩展方法上的 lambda 表达式,仅从对象获取属性
本文关键字:对象 获取 属性 表达式 方法 lambda 扩展 | 更新日期: 2023-09-27 18:33:07
我正在编写一个小型验证流畅的 API 来验证我通过以下方式使用的命令:
Validator.Candidate(foo).Verify(x => x.Name).IsNotNull();
实际上,verify 方法将 lambda 表达式的值(在本例中为从 foo.Name
属性中提取的字符串(传递给一组扩展方法,例如 IsNotNull()
、IsGreaterThan(10)
等。然后,如果需要,扩展方法可以引发错误,依此类推。
API 中使用的基础类和扩展方法包括:
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; }
}
上面显示的IsNotNull()
扩展并不重要,与手头的问题无关。
问题是在Verify()
方法中,我传递了一个lambda来选择Candidate()
中使用的对象的属性。
我希望能够做的是将Verify()
中使用的lambda限制为仅允许传入候选对象的属性,即如果候选对象定义为:
public Foo() {
string Name { get; set; }
}
我希望能够做到:
Validator.Object(instanceOfFoo).Verify(x => x.Name).....
但不是:
Validator.Object(instanceOfFoo).Verify(x => "Hello")....
目前,上述两种用法都将编译。我认为这是因为我在 lamda 中写了 lamda 的签名,Verify
写错了我想做的事情,并且不知道如何写它来做我想做的事情!
lambda需要这样编写,如果尝试将某些内容传递到不是Foo属性(或任何用作候选对象的对象(的Verify
中,则会抛出编译器错误。 我不想在运行时进行检查。
无法
在 C# 中表达该约束,因此编译器无法在编译时检查它。
但是,可以使用静态代码分析在运行时之前捕获它。最简单的方法可能是使用 Roslyn: https://msdn.microsoft.com/en-us/magazine/dn879356.aspx
这样,您可以立即向开发人员提供反馈,并在构建时捕获任何错误。