Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用DynamicMethod调用具有泛型参数的方法?_C#_.net_Sorting_Dynamicmethod_Dynamic Method - Fatal编程技术网

C# 使用DynamicMethod调用具有泛型参数的方法?

C# 使用DynamicMethod调用具有泛型参数的方法?,c#,.net,sorting,dynamicmethod,dynamic-method,C#,.net,Sorting,Dynamicmethod,Dynamic Method,我的目标是创建一个方法SortRecords,它接受IEnumerable和PropertyInfo作为参数。IEnumerable是一个记录列表。属性info是T的属性。调用时,SortRecords应使用x=>x.Property调用Enumerable.SortBy方法。请注意,Enumerable.SortBy有两个通用参数。此外,反射不能在lambda表达式中使用,因为(a)它速度慢,(b)它不能与实体框架一起工作 我已经编写了一些代码,但我一直看到错误消息操作可能会破坏运行时的稳定性

我的目标是创建一个方法
SortRecords
,它接受
IEnumerable
PropertyInfo
作为参数。
IEnumerable
是一个记录列表。
属性info
T
的属性。调用时,
SortRecords
应使用
x=>x.Property
调用
Enumerable.SortBy
方法。请注意,
Enumerable.SortBy
有两个通用参数。此外,反射不能在lambda表达式中使用,因为(a)它速度慢,(b)它不能与实体框架一起工作

我已经编写了一些代码,但我一直看到错误消息
操作可能会破坏运行时的稳定性。下面是我的代码

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);
         }
for(int i=0;ip.Name==propertyName);
Func sortingFunction=GetFunctionToSortRecords(filteredRecords,属性);
sortedRecords=GetFunctionToSortRecords(filteredRecords,属性)(filteredRecords,属性);
}
结束第一个代码段

方法定义如下

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;
    }
将IEnumerable GetFunction委托给OrtRecordsDelegate(IEnumerable记录、PropertyInfo propertyToSortOn);
公共静态函数GetFunctionToSortRecords(IEnumerable记录、PropertyInfo propertyToSortOn)
{
类型propertyType=propertyToSortOn.GetType();
DynamicMethod=newdynamicmethod(“SortRecords”,typeof(IEnumerable),newtype[]{typeof(IEnumerable),typeof(PropertyInfo)});
ILGenerator=method.GetILGenerator();
MethodInfo GetPropertyValue=propertyToSortOn.GetGetMethod();
MethodInfo GetDefaultKeySelectorForProperty=typeof(DataTablesSorting).GetMethod(“GetDefaultKeySelectorForProperty”)
.MakeGenericMethod(新类型[]{typeof(T),propertyToSortOn.PropertyType});
MethodInfo EnumerableOrderBy=typeof(Enumerable).GetMethods()
.Single(m=>m.Name==“OrderBy”&&m.GetParameters().Count()==3);
//获取传入属性的默认键选择器。
generator.Emit(操作码.Ldarg_1);//属性
generator.Emit(操作码.Call,GetDefaultKeySelectorForProperty);
//将默认键选择器保存在位置0
生成器.Emit(操作码.Stloc_0);
generator.Emit(操作码.Ldarg_0);//记录
generator.Emit(OpCodes.Ldloc_0);//默认键选择器
generator.Emit(操作码.Call,EnumerableOrderBy);
生成器.Emit(操作码.Ret);
return((GetFunctionToSortRecordsDelegate)(method.CreateDelegate(typeof(GetFunctionToSortRecordsDelegate))).Invoke;
}
委托TKey GetDefaultKeySelectorForPropertyLegate(T);
公共静态函数GetDefaultKeySelectorForProperty(PropertyInfo属性)
{
DynamicMethod=newdynamicmethod(“GetKeySelector”,typeof(TKey),newtype[]{typeof(T)});
ILGenerator=method.GetILGenerator();
MethodInfo GetPropertyValue=property.GetMethod();
生成器.Emit(操作码.Ldarg_0);
Emit(opcode.Callvirt,GetPropertyValue);
生成器.Emit(操作码.Ret);
return((GetDefaultKeySelectorForPropertyDelegate)(method.CreateDelegate(typeof(GetDefaultKeySelectorForPropertyDelegate))).Invoke;
}

我认为这个问题可能是相关的:

我自己没有像这样使用过
动态方法
,但我怀疑你只需要在
EnumerableOrderBy上使用
MakeGenericMethod
,就像你已经在为
GetDefaultKeySelectorForProperty
做的那样。目前,您正在尝试在不指定任何类型参数的情况下调用泛型方法

比如:

MethodInfo EnumerableOrderBy = typeof(Enumerable).GetMethods()
    .Single(m => m.Name == "OrderBy" && m.GetParameters().Count() == 3)
    .MakeGenericMethod(typeof(T), propertyToSortOn.PropertyType);
(使用参数数组,因此无需显式构造
类型[]
即可传入。)


(如果您需要使用实体框架,我一直认为您应该考虑
Queryable
,而不是
Enumerable
,并构建表达式树而不是委托,但这是另一回事。)

我更喜欢使用表达式解决此类问题。下面是一个适合您的示例

    public static Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>> GetFunctionToSortRecords<T>(IEnumerable<T> records, PropertyInfo property)
    {
        var propertyExpression = GetExpressionForProperty<T>(property);
        var method = typeof(TheCurrentClass).GetMethod("InternalGetFunctionToSortRecords", BindingFlags.NonPublic | BindingFlags.Static);

        return (Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>>)method.MakeGenericMethod(typeof(T), property.PropertyType).Invoke(null, new object[] { propertyExpression });
    }

    private static Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>> InternalGetFunctionToSortRecords<T, TProp>(Expression propertyExpression)
    {
        var lambdaExpression = propertyExpression as LambdaExpression;
        Func<T, TProp> keySelector = (Func<T, TProp>)lambdaExpression.Compile();
        Func<IEnumerable<T>, PropertyInfo, IEnumerable<T>> sorter = (x, y) => x.OrderBy(keySelector);

        return sorter.Invoke;
    }

    private static Expression GetExpressionForProperty<T>(PropertyInfo property)
    {
        var parameter = Expression.Parameter(typeof(T));
        var propertyExpression = Expression.Property(parameter, property);
        var lambdaExpression = Expression.Lambda(propertyExpression, parameter);

        return lambdaExpression;
    }
公共静态函数GetFunctionToSortRecords(IEnumerable记录,PropertyInfo属性)
{
var propertyExpression=GetExpressionForProperty(属性);
var method=typeof(当前类).GetMethod(“InternalGetFunctionToSortRecords”,BindingFlags.NonPublic | BindingFlags.Static);
return(Func)method.MakeGenericMethod(typeof(T),property.PropertyType).Invoke(null,新对象[]{propertyExpression});
}
私有静态函数InternalGetFunctionToSortRecords(表达式属性Expression)
{
var lambdaExpression=propertyExpression作为lambdaExpression;
Func keySelector=(Func)lambdaExpression.Compile();
Func-sorter=(x,y)=>x.OrderBy(键选择器);
返回分类器。调用;
}
私有静态表达式GetExpressionForProperty(PropertyInfo属性)
{
var参数=表达式参数(typeof(T));
var propertyExpression=Expression.Property(参数,属性);
var lambdaExpression=Expression.Lambda(propertyExpression,参数);
返回lambdaExpression;
}

毫无疑问,您已经做了一个重要的观察,但即使我应用了您建议的更改,我仍然会发现
操作可能会破坏运行时的稳定性。@Danielallengdon:在哪一点上?这里有一个简短但完整的例子,如果你能用一个较短的IL块(例如p