jeudi 5 juillet 2018

Expression.Lambda can't convert types automatically

I have some properties in many classes and want to compile getter/setter of them into lambda expressions so that I can use reflections with better performance.

(Profiled, and using Reflection's getValue/setValue takes up about 78% of total running time...)

However It seems that Expression.Lambda() Only supports one collection of parameter and will not convert parameter type automatically.

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);

It will thorw an exception:

ParameterExpression of type __Main__+A cannot be used for delegate parameter of type System.Object

If I change the expression into Exp.Lambda<Func<A, int>>(...) it will work with class A but will not work with class B.

If I use Expression.Convert to convert types, it will throw ArgumentException that tells me the method cannot invoke on instance of System.Object.

So what can I do to compile this expression just like below, which supports any type of object and corresponding method? lambda = (object obj, MethodInfo method, ...) => { method.Invoke(obj, ...) }





Aucun commentaire:

Enregistrer un commentaire