Jim*_*m C 36 c# lambda delegates properties
我创建了将属性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;
}
Run Code Online (Sandbox Code Playgroud)
这些工作:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
Run Code Online (Sandbox Code Playgroud)
但这些不会编译:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Run Code Online (Sandbox Code Playgroud)
MakeSetter行失败,"无法根据用法推断出类型参数.请尝试明确指定类型参数."
我正在尝试做什么?提前致谢.
Mar*_*ell 57
该ExpressionAPI支持这在.NET 4.0中,但遗憾的是C#编译器不会增加任何额外的糖果支持.但好消息是,您可以轻松地采用"获取"表达式(C#编译器可以编写)并将其重写为"set"表达式.
甚至更好; 如果你没有.NET 4.0,那么至少还有两种方法可以通过写成"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
}
}
Run Code Online (Sandbox Code Playgroud)
Sti*_*tix 18
根据我的评论 - 因为链接已经死了 - 我已经发布了完整的代码作为问题的答案.是的,可以做OP请求的事情.这是尼克展示它的一个不错的小宝石.Nick将此页面和其他页面归功于他的完整解决方案以及性能指标.我在下面提供,而不仅仅是一个链接.
// returns property getter
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");
Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
Func<TObject, TProperty> result =
Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();
return result;
}
// returns property setter:
public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
{
ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));
ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);
MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
(
Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
).Compile();
return result;
}
Run Code Online (Sandbox Code Playgroud)
Action<T>表示一个委托,它接受一个类型的参数T并且不返回任何内容。您提供的 lambda 表达式用于MakeSetter表示不带参数并返回 或 的SomeClass.SomeProperty委托someObject.SomeProperty。
您收到的错误消息是由于编译器无法从您传递到方法中的 lambda 表达式推断出类型,MakeSetter因为您传递的内容和方法期望的内容不同步。
| 归档时间: |
|
| 查看次数: |
23318 次 |
| 最近记录: |