Как создать скомпилированную лямбду с вызовами методов?

Я генерирую скомпилированные методы getter во время выполнения для данного члена. Прямо сейчас, мой код просто предполагает, что результат метода getter является строкой (отлично подходит для тестирования). Тем не менее, я хотел бы сделать эту работу с настраиваемым classом конвертера, который я написал, см. Ниже ссылку «ConverterBase», которую я добавил.

Я не могу понять, как добавить вызов classа конвертера в мое дерево выражений.

public Func GetGetter(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)getter.Compile(); } 

Я ищу, что поставить во вторую область TODO (я могу справиться с первым :)).

Полученная скомпилированная lambda должна взять экземпляр типа U в качестве параметра, вызвать указанную функцию доступа к члену, затем вызвать метод преобразователя «FieldToString» с результатом и вернуть результирующую строку.

Можете ли вы проиллюстрировать, что (если это был обычный C #), который вы хотите, чтобы выражение оценивалось? Я могу написать выражение достаточно легко – я просто не совсем понимаю вопрос …

(отредактируйте re comment) – в этом случае это будет что-то вроде:

  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>( Expression.Call(converter, typeof(ConverterBase).GetMethod("FieldToString"), getter), target).Compile(); 

Или, если тип отказывается связывать, вам нужно ввести cast / convert:

  MethodInfo method = typeof(ConverterBase).GetMethod("FieldToString"); return Expression.Lambda>( Expression.Call(converter, method, Expression.Convert(getter, method.GetParameters().Single().ParameterType)), target).Compile(); 

Вам нужно обернуть объект в 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 f = (Func) intToStr.Compile(); Console.WriteLine(f(42)); Console.ReadLine(); }