【发布时间】:2015-11-22 22:31:50
【问题描述】:
我有这个方法,使用Expressions 创建字段getter:
public static Func<object, T> CreateFieldValueGetter<T>(this Type declaringType, FieldInfo fieldToGet) {
var paramExp = Expression.Parameter(typeof(object));
// ArgumentException if declaringType describes generic-type:
var cast = Expression.Convert(paramExp, declaringType);
var body = Expression.Field(cast, fieldToGet);
return Expression.Lambda<Func<object, T>>(body, paramExp).Compile();
}
在我给它一个通用类型之前它工作得很好:
class DataErrorNotifyingViewModelBase<TErr> : ViewModelBase, INotifyDataErrorInfo
where TErr : struct, IConvertible, IComparable, IFormattable
{
// ...
}
这边:
var vm = new DataErrorNotifyingViewModelBase<MyErrorsTypeEnum> ();
var type = vm.GetType();
// ArgumentException:
var getter = type.CreateFieldValueGetter<PropertyChangedEventHandler>(type.GetField("PropertyChanged"));
这是我得到的例外:
Exception thrown: 'System.ArgumentException' in System.Core.dll
Additional information: Type GuiHelpers.DataErrorNotifyingViewModelBase`1[TErr] is a generic type definition
虽然简单的铸造工作:
var vm = new DataErrorNotifyingViewModelBase<PrintDialogError>();
var obj = (object) vm;
那么我怎样才能给它提供泛型类型呢?我是否仅限于非泛型类型?
编辑 - 解决方案:
Kaveh Hadjari 抓住了它:
传递t = typeof (Dictionary<T, int>) 将引发ArgumentException,因为t.GetGenericArguments()[0].IsGenericParameter 是true(尽管t.GetGenericArguments()[1].IsGenericParameter 是false!)
传递t = typeof (Dictionary<int, int>) 类型可以正常工作,因为t.GetGenericArguments() 数组的任何元素都没有IsGenericParameter == true
【问题讨论】:
-
您的代码无法编译。
type.CreateFieldValueGetter<PropertyChangedEventHandler>(type.GetField("PropertyChanged"));无法编译,因为您的方法不是扩展方法。 然而,解决这个问题后,您的代码可以正常工作。请准确地向我们展示您正在使用的代码。 -
无法重现该问题;似乎对我来说工作正常。也许你把这个例子简化得太多了?
-
请看这个简化的小提琴,表明你的
CreateFieldValueGetter方法确实有效:dotnetfiddle.net/iVTzio -
@Rob,已修复,谢谢。
标签: c# generics lambda expression expression-trees