我想将强类型属性传递给一个方法,并将此属性名称用作mhy集合的字符串,所以我找到了一些代码,可以在其中传递强类型属性:
public static void Add<TObject, TProperty>(this NameValueCollection collection, Expression<Func<TObject, TProperty>> expression, string value)
{
var member = expression.Body as MemberExpression;
collection.Add(member.Member.Name, value);
}
这是有效的,而且做了我想要的,但我想知道这到底是怎么回事。我感兴趣的部分是方法(Add<Tobject, TProperty>
)与Func
表达式的通用参数。有人能向我解释一下这是怎么回事吗?为什么我可以像collection.Add((MyObject m) => m.FullName, "Martijn")
一样调用这个方法?为什么不需要使用Add<MyObject, ???>(m => m.FullName, "Martijn")
?
更新:我现在已经将我的方法重构为:
public static void Add<TObject>(this NameValueCollection collection, Expression<Func<TObject, string>> expression, string value)
{
var member = expression.Body as MemberExpression;
collection.Add(member.Member.Name, value);
}
Expression<T>
是一个表达式树,具有委托类型T
的签名。表达式树很复杂,但基本上:这不是操作的委托,而是描述操作的对象模型,可以检查它是如何组成的。
因此,Expression<Func<TObject,TProperty>>
是表示接受TObject
参数并返回TProperty
结果的事物的表达式树。
至于为什么不需要手动告诉它<MyObject, ???>
:这是泛型类型推理,是正常的。给定一个通用方法,比如:
void Foo<T>(T bar);
您可以将其称为:
Foo<string>("abc");
但你也可以使用:
Foo("abc");
然后,编译器将检查这些参数,看看它是否能够解析所有的泛型类型参数——在这种情况下,"abc"
是string
,而引脚T
是string
。如果它可以解析所有,则无需指定它们。
在您的示例中,TObject
被固定,因为您的lambda通过(MyObject) m
显式获取MyObject
,而TProperty
被固定到(可能)string
,因为m.FullName
(可能)返回string
。由于所有泛型类型参数都已自动解析,因此不需要手动指定<...>
。
请注意,泛型类型推理仅适用于泛型方法(通过参数),而不适用于泛型类型。