Я создаю фреймворк, который позволяет веб-разработчикам создавать страницы CRUD без необходимости проходить через повторяющиеся шаги.Как определить параметры типа из моего кода, который использует DynamicMethod и Entity Framework?
С этой целью я хочу предоставить методы «по умолчанию», которые выполняют такие функции, как сортировка, фильтрация и т. П. Разработчик, использующий мою инфраструктуру, может предоставить свой собственный метод, если он захочет, но должен быть метод по умолчанию, который работает во многих случаях.
Для меня особенно важно, чтобы это было совместимо с Entity Framework.
Я успешно реализовал функцию фильтрации по умолчанию, используя класс DynamicMethod
, который позволяет «генерировать» фильтрацию ключом поиска на произвольных классах, сгенерированных Entity Framework.
Я пытаюсь сделать что-то подобное с сортировкой, но у меня проблема. Метод OrderBy
принимает два типа параметров, первым из которых является тип сущности, а второй - тип ключа. Этот введенный ключ должен соответствовать типу столбца, который пользователь хочет сортировать, и для того, чтобы это работало со всеми классами сущностей, тип должен определяться во время выполнения.
Я использовал отражение, чтобы обнаружить тип столбца, но я не знаю, как отличить функцию «сравнения» с соответствующим типом Func <>. Поэтому я установил оператор switch, который включает тип. Я хочу избавиться от оператора switch и разделить тип ключа.
Как это сделать? Мой код следует ниже:
public override IEnumerable<T> GetSortedRecords<T>(IEnumerable<T> filteredRecords)
{
// The goal here is to allow for a developer to provide a method for sorting records,
// but to also provide a default method that will work with all instances of EntityObject.
// To that end, I believe it is necessary to use the fun fun DynamicMethod object.
// Note - check for ASC vs DESC
if (NumberOfSorts == 0)
return filteredRecords;
IOrderedEnumerable<T> sortedRecords = null;
for (int i = 0; i < NumberOfSorts; i++)
{
string propertyName = PropertyNames[ColumnSortOrder[i]];
PropertyInfo property = typeof(T).GetProperties().Single(p => p.Name == propertyName);
switch (property.PropertyType.Name)
{
// I want to get rid of these branches.
case "Int32":
Func<T, int> comparerInt32 = GetDefaultKeySelectorForProperty<T, Int32>(property);
sortedRecords = i == 0 ?
filteredRecords.OrderBy<T, int>(comparerInt32) :
sortedRecords.ThenBy<T, int>(comparerInt32);
break;
case "String":
Func<T, string> comparerString = GetDefaultKeySelectorForProperty<T, string>(property);
sortedRecords = i == 0 ?
filteredRecords.OrderBy<T, string>(comparerString) :
sortedRecords.ThenBy<T, string>(comparerString);
break;
default:
throw new NotImplementedException();
}
}
return sortedRecords;
}
delegate TKey GetDefaultKeySelectorForPropertyDelegate<T, TKey>(T t);
public Func<T, TKey> GetDefaultKeySelectorForProperty<T, TKey>(PropertyInfo property)
{
DynamicMethod method = new DynamicMethod("GetKeySelector", typeof(TKey), new Type[] { typeof(T) });
ILGenerator generator = method.GetILGenerator();
MethodInfo GetPropertyValue = property.GetGetMethod();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Callvirt, GetPropertyValue);
generator.Emit(OpCodes.Ret);
return ((GetDefaultKeySelectorForPropertyDelegate<T, TKey>)(method.CreateDelegate(typeof(GetDefaultKeySelectorForPropertyDelegate<T, TKey>)))).Invoke;
}
Вы можете, как [этот] (http://stackoverflow.com/q/41244/861716). –