我在运行时为给定成员生成编译的getter方法。现在,我的代码只是假设getter方法的结果是一个字符串(适用于测试)。但是,我想使用我编写的自定义转换器类来完成这项工作,请参阅下面的“ConverterBase”参考资料。
我无法弄清楚如何将对转换器类的调用添加到我的表达式树中。
public Func<U, string> GetGetter<U>(MemberInfo info)
{
Type t = null;
if (info is PropertyInfo)
{
t = ((PropertyInfo)info).PropertyType;
}
else if (info is FieldInfo)
{
t = ((FieldInfo)info).FieldType;
}
else
{
throw new Exception("Unknown member type");
}
//TODO, replace with ability to specify in custom attribute
ConverterBase typeConverter = new ConverterBase();
ParameterExpression target = Expression.Parameter(typeof(U), "target");
MemberExpression memberAccess = Expression.MakeMemberAccess(target, info);
//TODO here, make the expression call "typeConverter.FieldToString(fieldValue)"
LambdaExpression getter = Expression.Lambda(memberAccess, target);
return (Func<U, string>)getter.Compile();
}
我正在寻找第二个TODO区域的内容(我可以处理第一个:))。
生成的编译lambda应该将U类型的实例作为参数,调用指定的成员访问函数,然后使用结果调用转换器的“FieldToString”方法,并返回结果字符串。
答案 0 :(得分:5)
您能说明您希望表达式评估的内容(如果是常规C#)吗?我可以很容易地写出表达式 - 我只是不完全理解这个问题......
(编辑评论) - 在这种情况下,它将是:
ConverterBase typeConverter = new ConverterBase();
var target = Expression.Parameter(typeof(U), "target");
var getter = Expression.MakeMemberAccess(target, info);
var converter = Expression.Constant(typeConverter, typeof(ConverterBase));
return Expression.Lambda<Func<U, string>>(
Expression.Call(converter, typeof(ConverterBase).GetMethod("FieldToString"),
getter), target).Compile();
或者如果类型拒绝绑定,则需要注入一个强制转换/转换:
MethodInfo method = typeof(ConverterBase).GetMethod("FieldToString");
return Expression.Lambda<Func<U, string>>(
Expression.Call(converter, method,
Expression.Convert(getter, method.GetParameters().Single().ParameterType)),
target).Compile();
答案 1 :(得分:4)
您需要将对象包装在ExpressionConstant中,例如通过使用Expression.Constant。这是一个例子:
class MyConverter
{
public string MyToString(int x)
{
return x.ToString();
}
}
static void Main()
{
MyConverter c = new MyConverter();
ParameterExpression p = Expression.Parameter(typeof(int), "p");
LambdaExpression intToStr = Expression.Lambda(
Expression.Call(
Expression.Constant(c),
c.GetType().GetMethod("MyToString"),
p),
p);
Func<int,string> f = (Func<int,string>) intToStr.Compile();
Console.WriteLine(f(42));
Console.ReadLine();
}