我面临以下代码,通过反思检索数据:
public object GetValue(object source)
{
if (Member == null) return Argument;
try
{
object[] argList = (Argument == null ? null : new object[] { Argument });
if (Member is PropertyInfo) return ((PropertyInfo)Member).GetValue(source, argList);
if (Member is MethodInfo) return ((MethodInfo)Member).Invoke(source, argList);
if (Member is FieldInfo) return ((FieldInfo)Member).GetValue(source);
throw new Exception("Unknown member type: " + Member);
}
catch (Exception ex)
{
throw new Exception("Could not get value " + Member.Name + " from " + source + " with " + Argument, ex);
}
}
然而这很慢,我想用更快的东西取代反射,也许是代表?但是,我不确定代表是最佳选择还是在这种情况下如何实现它。我正在运行.NET 4.0。任何建议都表示赞赏!
答案 0 :(得分:1)
这快一点
static Func<object, object[], object> BuildCaller(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object));
var pars = Expression.Parameter(typeof(object[]));
var pars2 = method.GetParameters();
var casted = new Expression[pars2.Length];
for (int i = 0; i < pars2.Length; i++)
{
casted[i] = Expression.Convert(Expression.ArrayAccess(pars, Expression.Constant(i)), pars2[i].ParameterType);
}
var call = Expression.Call(Expression.Convert(obj, method.DeclaringType), method, casted);
var cast = Expression.Convert(call, typeof(object));
var lamdba = Expression.Lambda<Func<object, object[], object>>(cast, obj, pars);
return lamdba.Compile();
}
static Func<object, object[], object> BuildCaller(FieldInfo field)
{
var obj = Expression.Parameter(typeof(object));
var pars = Expression.Parameter(typeof(object[]));
var call = Expression.Field(Expression.Convert(obj, field.DeclaringType), field);
var cast = Expression.Convert(call, typeof(object));
var lamdba = Expression.Lambda<Func<object, object[], object>>(cast, obj, pars);
return lamdba.Compile();
}
static Func<object, object[], object> BuildCaller(PropertyInfo property)
{
var obj = Expression.Parameter(typeof(object));
var pars = Expression.Parameter(typeof(object[]));
var pars2 = property.GetIndexParameters();
var casted = new Expression[pars2.Length];
for (int i = 0; i < pars2.Length; i++)
{
casted[i] = Expression.Convert(Expression.ArrayAccess(pars, Expression.Constant(i)), pars2[i].ParameterType);
}
var call = Expression.Property(Expression.Convert(obj, property.DeclaringType), property, casted);
var cast = Expression.Convert(call, typeof(object));
var lamdba = Expression.Lambda<Func<object, object[], object>>(cast, obj, pars);
return lamdba.Compile();
}
我创建了一个委托(通过Expression
)来预防该方法。如果Arguments
被“修复”,您可以更进一步,甚至可以预先设置转换(就像每次调用方法时都进行转换一样)
这是方法的一个例子。对于属性和字段,它是相似的(对于字段来说,它更容易)。
使用示例
var fun = BuildCaller(typeof(MyClass).GetMethod("MyMethod"));
var mc = new MyClass();
fun(mc, new object[] { 1, 2.0 });
您必须将fun
与Method