5

这是我用于测试类型扩展方法的类的片段:

class Something
{
  [StringLength(100, MinimumLength = 1, ErrorMessage = "Must have between 1 and 100 characters")]
  public string SomePublicString { get; set; }
}

我有以下扩展方法:

public static class TypeExtensions
{
  public static TAttributeType GetCustomAttribute<T, TAttributeType, TProperty>(this T value, Expression<Func<T, TProperty>> propertyLambda, bool inherit = false)
  {
    var type = typeof(T);
    var member = (MemberExpression)propertyLambda.Body;
    var propertyInfo = (PropertyInfo)member.Member;
    var customAttributes = propertyInfo.GetCustomAttributes(typeof(TAttributeType), inherit);

    return customAttributes.OfType<TAttributeType>().FirstOrDefault();
  }
}

单元测试中的用法:

1:  var something = new Something();
2:  var actual = something.GetCustomAttribute<Something, StringLengthAttribute, string>(x => x.SomePublicString);

3:  actual.MinimumLength.Should().Be(1);
4:  actual.MaximumLength.Should().Be(100);
5:  actual.ErrorMessage.Should().Be("Must have between 1 and 100 characters");

这将返回一个通过测试(使用 FluentAssertions)。

但是,我想在第 2 行中对 GetCustomAttribute() 的方法调用如下:

var actual = something.GetCustomAttribute<StringLengthAttribute>(x => x.SomePublicString);

这可能吗?我错过了什么吗?也许我正在喝咖啡因崩溃。:(

4

2 回答 2

7

不,您要么必须指定所有类型参数,要么都不指定。没有“部分”类型推断。

但是,有时您可以摆脱这种情况的一种方法是使用一个具有单个类型参数的泛型方法,该方法返回泛型类的实例,然后对其使用类型推断来完成其余的工作 - 反之亦然。在这种情况下,实际上最好将获取的属性与其他属性分开:

something.GetPropertyAttributes(x => x.SomePublicString)
         .FirstAttribute<StringLengthAttribute>();

这里第一个方法调用推断TTProperty- 并且只返回一个IEnumerable<Attribute>并且FirstAttribute只会执行OfType/FirstOrDefault调用。(您甚至可以决定不需要FirstAttribute,因为调用OfType和您FirstOrDefault自己非常简单。)

于 2013-04-04T16:05:15.750 回答
3

不可能推断出某些类型参数,但不是全部,不。

您可以:

  1. 指定所有通用参数。

  2. 确保可以推断出所有通用参数。(并不总是可能的,或者允许推理所需的妥协可能是不可取的。)

  3. 将方法分解为多种方法,一种方法推断通用参数,一种方法不推断。

于 2013-04-04T16:01:46.953 回答