【发布时间】:2017-10-16 03:45:35
【问题描述】:
简介 我正在编写一些严重依赖反射的代码。一些处于核心的部分被重复使用。以最轻微的方式对此进行优化都会给我带来很多(不同程度的)性能优势。
上下文 核心包括从对象中获取数据。目前我使用反射获取一个PropertyInfo对象,然后使用如下代码构造一个Func
public static Func<object, object> BuildUntypedGetter(PropertyInfo propertyInfo)
{
var targetType = propertyInfo.DeclaringType;
var methodInfo = propertyInfo.GetGetMethod();
var exTarget = System.Linq.Expressions.Expression.Parameter(typeof(object), "t");
var exBody0 = System.Linq.Expressions.Expression.Convert(exTarget, targetType);
var exBody = System.Linq.Expressions.Expression.Call(exBody0, methodInfo);
var exBody2 = System.Linq.Expressions.Expression.Convert(exBody, typeof(object));
var lambda = System.Linq.Expressions.Expression.Lambda<Func<object, object>>(exBody2, exTarget);
var action = lambda.Compile();
return action;
}
这个结果 Func
在上面的代码中,创建的 lambda 如下所示:
.Lambda #Lambda1<System.Func`2[System.Object,System.Object]>(System.Object $t) {
(System.Object).Call ((MyObjectType)$t).get_Id()
}
其中 Id 是生成它的属性。
如您所见,这只是一个重定向。它所做的只是调用 getter。
问题
有没有办法只返回 getter (get_Id) 作为 Func<object,object> 而无需额外的演员和调用?或者是否有其他更有效的方法来调用对象类型作为实例类型的 object.attribute getter?
【问题讨论】:
-
属性返回的是引用类型还是值类型?还是两者兼而有之?
-
值和引用类型都需要支持。不过我想我们可以提前从元数据中获取这些信息,然后在需要时生成差异化代码(例如,if (valuetype) { create value lambda } else { create reference lambda }。
-
嗯,有 Delegate.CreateDelegate 方法。不确定它是否允许投射对象。
-
我是一般人,不,这是不可能的。它要求输入类型
T是协变的,这是不合法的。此外,输出类型TReturn仅对引用类型是协变的;Func<,object>不能从Func<,int>或其他原始特殊特化中分配。 -
@Wazner 我已经检查过该方法。但是,据我了解(可能是错误的),委托被绑定到非静态方法的特定 instance 。我需要能够在不创建新委托的情况下调用多个对象的 getter
标签: c# optimization lambda