扩展方法上的 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中,则会抛出编译器错误。 我不想在运行时进行检查。

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

无法

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

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

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