以下是我用于测试Type扩展方法的类的片段:
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);
这可能吗?我错过了什么吗?也许我正在喝咖啡因。 :(
答案 0 :(得分:7)
不,您必须指定所有类型参数,或者不指定任何类型参数。没有“部分”类型推断。
但是,有时可以避免这种情况的一种方法是使用一个带有单一类型参数的泛型方法,该方法返回泛型类的实例,然后对其进行类型推断以完成其余操作 - 反之亦然。在这种情况下,实际上最好将属性提取与其余部分分开:
something.GetPropertyAttributes(x => x.SomePublicString)
.FirstAttribute<StringLengthAttribute>();
此处第一个方法调用推断T
和TProperty
- 只返回IEnumerable<Attribute>
而FirstAttribute
只会执行OfType
/ {{1}调用。 (您甚至可能认为自己不需要FirstOrDefault
,因为您自己致电FirstAttribute
和OfType
非常简单。)
答案 1 :(得分:3)
不可能推断出一些但不是全部的类型参数,没有。
你可以:
指定所有通用参数。
确保可以推断出所有通用参数。 (并非总是可行,或者允许推理所需的妥协可能是不可取的。)
将方法分解为多个方法,以便一个方法推断出通用参数,而另一个方法则不会。