如果性能是关键,我建议你使用CreateDelegate
结构。因为你预先知道方法的签名,也就是PropertyInfo
中的GetGetMethod
和GetSetMethod
,所以可以创建一个委托直接执行相同签名的方法。如果你需要构建一些逻辑(没有方法句柄)到委托,表达式会更适合。我对不同的解决方法进行了一些基准测试:
Func<S, T> Getter;
Action<S, T> Setter;
PropertyInfo Property;
public void Initialize(Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
Property = body.Member as PropertyInfo;
}
public T Get(S instance)
{
}
public void Set(S instance, T value)
{
}
Results for about 10000000 calls - (Get, Set):
GetValue-SetValue (direct): 3800 ms, 5500 ms
GetValue-SetValue (delegate): 3600 ms, 5300 ms
compiled expressions:
Get: Expression.Property: 280 ms
Expression.Call: 280 ms
direct compile: 280 ms
Set: 300 ms
create delegate: 130 ms, 135 ms
direct property call: 70 ms, 70 ms
如果我是你,我会写:
public static Func<S, T> BuildGetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetGetMethod().CreateDelegate<Func<S, T>>();
}
public static Action<S, T> BuildSetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetSetMethod().CreateDelegate<Action<S, T>>();
}
public static T CreateDelegate<T>(this MethodInfo method) where T : class
{
return Delegate.CreateDelegate(typeof(T), method) as T;
}
public static PropertyInfo GetPropertyInfo<S, T>(this Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
return body.Member as PropertyInfo;
}
现在你需要调用:
TestClass cwp = new TestClass()
var access = BuildGetAccessor((TestClass t) => t.AnyValue)
var result = access(cwp)
这不是更简单吗?我在这里写了一个通用类
处理这个确切的事情。