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 typeSystem.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