Ste*_*e G 2 c# properties expression-trees
我正在使用以下代码创建和缓存属性访问者委托:
static Delegate CreateGetterDelegate<T>(PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType);
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
}
Run Code Online (Sandbox Code Playgroud)
这是工作和运作良好(谢谢StackOverflow!),但是我想通过返回T和对象的Func来删除所需的装箱/拆箱.有没有办法改变返回,以便返回类型是T的Func和typeofproperty?
即
static Delegate CreateGetterDelegate<T>(PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
... some magic happening here ...
return (Func<T, typeofproperty>)Expression.Lambda(...more magic...).Compile();
}
Run Code Online (Sandbox Code Playgroud)
注意 - 我正在使用VS2013和.NET 4.5
唯一的方法是在编译时知道属性的类型,无论是在此方法定义中还是在调用者中.如果此方法的调用者知道属性的类型,那么它可以使用第二个泛型参数指定它:
static Func<TInstance, TResult> CreateGetterDelegate<TInstance, TResult>(
PropertyInfo propertyInfo)
{
if (typeof(TInstance) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType);
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
return (Func<TInstance, TResult>)Expression.Lambda(convert, instance)
.Compile();
}
Run Code Online (Sandbox Code Playgroud)
当然,这只是将问题推回给调用者.如果即使调用者不知道属性的类型是什么,那么他们也有完全相同的问题.
在一天结束时,为了避免装箱,某些代码需要在编译时知道这个属性的类型是什么.如果有人在某个地方,在编译时就会知道,那么你可以继续使用泛型来解决问题,直到你达到某个人可以使用实际已知类型的那一点.如果在编译时什么都不知道类型,那么这个问题确实没有任何解决方案.
你可能,如果你想获得技术,可以通过使事物比它们更加动态来避免装箱(使用反射来调用这些使用反射来做事物的方法)但是从技术的角度来看,你可能能够避免字面上的box命令,你会失去比你获得的更多的方式.这不是一个实际的解决方案.