Моя цель здесь заключается в создании метода SortRecords
, который принимает параметры IEnumerable<T>
и PropertyInfo
. IEnumerable<T>
- это список записей. PropertyInfo
является собственностью T
. При вызове SortRecords
следует использовать метод Enumerable.SortBy<T, typeof Property>
с x => x.Property
. Обратите внимание, что Enumerable.SortBy
имеет два общих параметра. Кроме того, отражение не может быть использовано внутри выражения лямбда, потому что (а) оно медленное и (б) оно не будет работать с Entity Framework.Использование DynamicMethod для вызова метода с общими параметрами?
Я написал код, но я продолжаю видеть сообщение об ошибке Operation could destabilize the runtime
. Вот то, что мой код выглядит
for (int i = 0; i < NumberOfSorts; i++)
{
string propertyName = PropertyNames[ColumnSortOrder[i]];
PropertyInfo property = typeof(T).GetProperties().Single(p => p.Name == propertyName);
Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>> sortingFunction = GetFunctionToSortRecords<T>(filteredRecords, property);
sortedRecords = GetFunctionToSortRecords<T>(filteredRecords, property)(filteredRecords, property);
}
конца первого фрагмент код
определение метод следует
delegate IEnumerable<T> GetFunctionToSortRecordsDelegate<T>(IEnumerable<T> records, PropertyInfo propertyToSortOn);
public static Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>> GetFunctionToSortRecords<T>(IEnumerable<T> records, PropertyInfo propertyToSortOn)
{
Type propertyType = propertyToSortOn.GetType();
DynamicMethod method = new DynamicMethod("SortRecords", typeof(IEnumerable<T>), new Type[] { typeof(IEnumerable<T>), typeof(PropertyInfo) });
ILGenerator generator = method.GetILGenerator();
MethodInfo GetPropertyValue = propertyToSortOn.GetGetMethod();
MethodInfo GetDefaultKeySelectorForProperty = typeof(DataTablesSorting).GetMethod("GetDefaultKeySelectorForProperty")
.MakeGenericMethod(new Type[] {typeof(T), propertyToSortOn.PropertyType });
MethodInfo EnumerableOrderBy = typeof(Enumerable).GetMethods()
.Single(m => m.Name == "OrderBy" && m.GetParameters().Count()==3);
// Get the default key selector for the property passed in.
generator.Emit(OpCodes.Ldarg_1); // property
generator.Emit(OpCodes.Call, GetDefaultKeySelectorForProperty);
// Save the default key selector at location 0
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldarg_0); // records
generator.Emit(OpCodes.Ldloc_0); // default key selector
generator.Emit(OpCodes.Call, EnumerableOrderBy);
generator.Emit(OpCodes.Ret);
return ((GetFunctionToSortRecordsDelegate<T>)(method.CreateDelegate(typeof(GetFunctionToSortRecordsDelegate<T>)))).Invoke;
}
delegate TKey GetDefaultKeySelectorForPropertyDelegate<T, TKey>(T t);
public static 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;
}
Я думаю, что этот вопрос может быть связан: DynamicMethod with generic type parameters
Вы, несомненно, сделали важное замечание, но даже когда я применяю предложенное изменение, я все равно получаю сообщение об ошибке «Операция может дестабилизировать время выполнения». –
@ DanielAllenLangdon: В какой момент? Здесь поможет короткий, но полный пример - если вы можете воспроизвести его с более коротким блоком IL (например, передать делегату заказа), который тоже поможет. –
Я попытался переписать код с помощью отражения и обнаружил, что мне нужен двухпараметрический метод 'OrderBy'. Я думаю, что это определенно одна проблема, но я все еще получаю то же сообщение об ошибке при попытке использовать Dynamic Method. Я думаю, что, возможно, решение может состоять в том, чтобы чисто обернуть общий метод OrderBy в методе, который использует динамический метод и вызывать это ... –