У меня есть некоторые свойства во многих классах, и я хочу скомпилировать их методы получения / установки в лямбда-выражения, чтобы я мог использовать отражения с большей производительностью.
(Профилируется, и использование getValue / setValue в Reflection занимает около 78% от общего времени выполнения ...)
Однако, похоже, что Expression.Lambda () поддерживает только один набор параметров и не будет автоматически преобразовывать тип параметра.
using Exp = System.Linq.Expressions.Expression;
...
public class A { public int propA { get; set; } }
public class B { public int propB { get; set; } }
static Func<object, int> BuildFunc(Type type, string propName)
{
var param = Exp.Parameter(prop.DeclaringType, "x");
var exBody = Exp.Call(param, prop.GetGetMethod());
return Exp.Lambda<Func<object, int>>(exBody, param).Compile();
}
...
var a = new A();
var b = new B();
var fA = BuildFunc(typeof(A).GetProperty("propA"));
var fB = BuildFunc(typeof(B).GetProperty("propB"));
fA(a);
fB(b);
Это вызовет исключение:
ParameterExpression типа __Main__+A
нельзя использовать для параметра делегата типа System.Object
Если я изменю выражение на Exp.Lambda<Func<A, int>>(...)
, оно будет работать с классом A, но не будет работать с классом B.
Если я использую Expression.Convert
для преобразования типов, он выдаст ArgumentException, который говорит мне, что метод не может быть вызван в случае экземпляра System.Object
.
Итак, что я могу сделать, чтобы скомпилировать это выражение, как показано ниже, которое поддерживает любой тип объекта и соответствующий метод?
lambda = (object obj, MethodInfo method, ...) => { method.Invoke(obj, ...) }