我正在尝试根据特定标准序列化某些内容。
为此,我最初的希望是在对象的属性上使用包含lambda表达式的属性。
然而,由于无法做到这一点,我已经决定使用Func< T,bool>类中的成员,并通过property属性传递此Func的类型(或第一个参数类型)和名称。 E.g:
Func<SomeObject, bool> func = (p => p.Value == 4);
[FuncAtt(typeof(SomeObject), "func")]
public SomeObject PropertyName { get; set;}
在我的序列化程序中,我需要调用此Func&lt; T,bool&gt;。
假设在这种情况下我有一个类型t等于typeof(SomeObject),或者更抽象地,typeof(T)。我也可以得到Func&lt; T,bool&gt;本身,但只能通过反射作为对象。
我天真的做法是这样的:
object func = typeof(MyClass).GetField(attribute.FuncName).GetValue(MyClassInstance);
Type funcType = typeof(Func<,>).MakeGenericType(attribute.Type, typeof(bool));
ParameterExpression p = Expression.Parameter(attribute.Type, objectToSerialize);
LambdaExpression l = Expression.Lambda(funcType, func, p); /* Won't work */
但这会导致将lambda转换为委托的问题,这显然是错误的。
我试过这个代替'func':
(Expression)((Action)(() => func))
但是依赖于func是一个方法调用而不是lambda。
那么,有人能指出我正确的方向吗?
答案 0 :(得分:4)
你可以做这样的事情,而不需要表达式:
public static class Test
{
public static Predicate<int> func = s => s > 20;
}
并获取值:
private void Form1_Load(object sender, EventArgs e)
{
var a = typeof(Test).GetField("func");
bool validates = ((Predicate<int>)a.GetValue(null)).Invoke(100);
}
编辑以在不知道类型的情况下获取值:
bool validates = (bool)((Delegate)a.GetValue(null)).DynamicInvoke(100);
答案 1 :(得分:1)
我认为您可以使用lambda表达式的Compile方法将其强制转换为委托。
这是我在MSDN上找到的内容:
表达式&lt;(&lt;(TDelegate&gt;)&gt;) type提供Compile方法, 编译由代表的代码 将表达式树转换为可执行文件 代表。这个可执行代码是 相当于可执行代码 本来会产生的 lambda表达式已分配给a 委托类型最初。
Here你可以找到它。
答案 2 :(得分:1)
不确定这是工作样本,但这是方法:
// not sure what are you doing in this line, but assume it should return
// a method name specified in the attribute, e.g. "func" in your example.
// Also "func" must be a method (static one in my example) of SomeObject class
String funcname = typeof(MyClass).GetField(attribute.FuncName).GetValue(MyClassInstance);
ParameterExpression param = Expression.Parameter(typeof(SomeObject), "p");
MethodCallExpression call = Expression.Call(SomeObject, funcname, new Type[] { typeof(SomeObject), typeof(Boolean) }, param);
LambdaExpression lambda = Expression.Lambda<Func<SomeObject, Boolean>>(call, param);
现在您可以像这样调用“func”方法:
Boolean result = lambda.Compile()(SomeObjectInstance);