C# ValidationService方法-“验证”;T2验证<;T1、T2>;(表达式,T2)“;vs";对象验证<;T1>;(表达、对象)“;

C# ValidationService方法-“验证”;T2验证<;T1、T2>;(表达式,T2)“;vs";对象验证<;T1>;(表达、对象)“;,c#,.net,generics,lambda,C#,.net,Generics,Lambda,我正在设计一个验证服务,我正在为Validate()的两个不同方法签名进行争论。两者都使用lambda表达式获取对象类型和属性,以验证给定值。有以下定义: public interface IValidationService { /// <summary> /// Validates the value of the property returned by the property expression. /// </summary>

我正在设计一个验证服务,我正在为Validate()的两个不同方法签名进行争论。两者都使用lambda表达式获取对象类型和属性,以验证给定值。有以下定义:

public interface IValidationService
{
    /// <summary>
    /// Validates the value of the property returned by the property expression.
    /// </summary>
    /// <typeparam name="T">The type of the object to validate.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="propertyExpression">The property expression.</param>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    TProperty Validate<T, TProperty>(Expression<Func<T, TProperty>> propertyExpression, TProperty value);

    /// <summary>
    /// Validates the value of the property returned by the property expression.
    /// </summary>
    /// <typeparam name="T">The type of the object to validate.</typeparam>
    /// <param name="propertyExpression">The property expression.</param>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    object Validate<T>(Expression<Func<T, object>> propertyExpression, object value);
}
公共接口IValidationService
{
/// 
///验证属性表达式返回的属性值。
/// 
///要验证的对象的类型。
///属性的类型。
///属性表达式。
///价值。
/// 
TProperty验证(表达式属性Expression,TProperty值);
/// 
///验证属性表达式返回的属性值。
/// 
///要验证的对象的类型。
///属性表达式。
///价值。
/// 
对象验证(表达式属性表达式、对象值);
}
以下是每种方法的单元测试,因此您可以看到使用上的差异:

[Test]
public void ValidateCustomerId_Method1()
{
    string id = "123456789123";
    string validatedId = _validationService.Validate<Customer, string>(x => x.Id, id);
    Assert.That(validatedId, Is.EqualTo("123456789"));
}

[Test]
public void ValidateCustomerId_Method2()
{
    string id = "123456789123";
    string validatedId = (string) _validationService.Validate<Customer>(x => x.Id, id);
    Assert.That(validatedId, Is.EqualTo("123456789"));
}
[测试]
public void ValidateCustomerId_Method1()
{
字符串id=“123456789123”;
字符串validatedId=\u validationService.Validate(x=>x.Id,Id);
断言(validatedId,Is.EqualTo(“123456789”));
}
[测试]
public void ValidateCustomerId_Method2()
{
字符串id=“123456789123”;
字符串validatedId=(字符串)\ u validationService.Validate(x=>x.Id,Id);
断言(validatedId,Is.EqualTo(“123456789”));
}
第一个有两个类型参数,一个用于对象类型(T),另一个用于属性/值类型(TProperty)。这个很好,因为返回类型是TProperty,但也有点烦人,因为它有两个类型参数

第二个对象类型只有一个类型参数。该值是一个对象,也返回一个对象。这很好,因为它只有一个类型参数,但也有点烦人,因为我必须将返回类型从对象转换为属性/值类型

我假设另一个选项是向接口添加一个类型参数IValidationService,这将消除两个签名中的对象类型参数(T):

public interface IValidationService<T>
{
    TProperty Validate<TProperty>(Expression<Func<T, TProperty>> propertyExpression, TProperty value);

    object Validate(Expression<Func<T, object>> propertyExpression, object value);
}
公共接口IValidationService
{
TProperty验证(表达式属性Expression,TProperty值);
对象验证(表达式属性表达式、对象值);
}

哪个签名最有意义,为什么?

如果你赞同你的界面想法,你可以使用
验证
,而不需要提供类型参数;编译器将通过检查方法参数的类型来推断类型参数


否则,我个人倾向于使用
Validate
,因为类型参数看起来比使用cast更“干净”。

我没有意识到可以从泛型接口推断TProperty。我喜欢。