我想将一个强类型属性传递给一个方法,并使用此属性名作为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);
}
答案 0 :(得分:1)
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
获取(MyObject) m
,并且TProperty
固定为(大概)a {{ 1}},因为string
(推测)会返回m.FullName
。由于所有通用类型参数都已自动解析,因此您无需手动指定string
。
请注意,泛型类型推断仅适用于通用方法(通过参数),而不适用于通用类型。