У меня есть этот метод, с помощью Expression
с для создания полей добытчиков:Expression.Convert (..., someGenericType) бросает ArgumentException при использовании общего типа
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;
Так как я могу кормить его с общими типами? Я ограничена только не-generic-типами?
Edit - решение:
Kaveh Hadjari поймал:
Передача t = typeof (Dictionary<T, int>)
не поднимет ArgumentException
как t.GetGenericArguments()[0].IsGenericParameter
является true
Передача типа t = typeof (Dictionary<int, int>)
работает отлично, becuse нет (хотя t.GetGenericArguments()[1].IsGenericParameter
это false
!) элемент массива t.GetGenericArguments()
имеет IsGenericParameter == true
Ваш код не компилируется. 'type.CreateFieldValueGetter (type.GetField (" PropertyChanged "));' не компилируется, так как ваш метод не является методом расширения. * Однако *, исправляя это, ваш код работает отлично. Пожалуйста, покажите нам * точно * код, который вы используете. –
Rob
Невозможно воспроизвести проблему; кажется, работает отлично для меня. Возможно, вы слишком упростили этот пример? –
См. Эту упрощенную скрипку, показывающую, что ваш метод 'CreateFieldValueGetter' действительно работает: https://dotnetfiddle.net/iVTzio –