我创建了将属性 lambda 转换为委托的方法:
public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
这些工作:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
但这些不会编译:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
MakeSetter 行失败并显示“无法从用法推断类型参数。请尝试显式指定类型参数。”
我想做的事情可能吗?提前致谢。
The Expression
API 在 .NET 4.0 中支持这一点,但遗憾的是 C# 编译器没有添加任何额外的支持。但好消息是,您可以轻松地采用“get”表达式(C# 编译器canwrite)并将其重写为“集合”表达式。
甚至更好;如果你没有.NET 4.0,还有at least通过写为“get”的表达式执行“set”的另外两种方法。
它们都在这里,供参考:
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo {
public string Bar { get; set; }
static void Main() {
// take a "get" from C#
Expression<Func<Foo, string>> get = foo => foo.Bar;
// re-write in .NET 4.0 as a "set"
var member = (MemberExpression)get.Body;
var param = Expression.Parameter(typeof(string), "value");
var set = Expression.Lambda<Action<Foo, string>>(
Expression.Assign(member, param), get.Parameters[0], param);
// compile it
var action = set.Compile();
var inst = new Foo();
action(inst, "abc");
Console.WriteLine(inst.Bar); // show it working
//==== reflection
MethodInfo setMethod = ((PropertyInfo)member.Member).GetSetMethod();
setMethod.Invoke(inst, new object[] { "def" });
Console.WriteLine(inst.Bar); // show it working
//==== Delegate.CreateDelegate
action = (Action<Foo, string>)
Delegate.CreateDelegate(typeof(Action<Foo, string>), setMethod);
action(inst, "ghi");
Console.WriteLine(inst.Bar); // show it working
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)