.NET 6中MakeGenericMethod调用Enumerable.Max失效问题求助
解决方案:.NET 6中反射获取
Enumerable.Max<TSource,TResult>重载 问题根源
.NET Framework与.NET 6中Enumerable类的Max方法重载布局发生了变化,原代码依赖参数泛型参数的索引位置做筛选,这种方式在框架版本变更后完全不可靠:
- 原代码访问
method.GetParameters()[1].ParameterType.GenericTypeArguments[1]时,.NET 6中该泛型参数数组长度不足,触发ArrayOutOfBoundsException - 修改后的代码误选了仅含1个泛型参数的
Max重载(比如Max<TSource>(IEnumerable<TSource>, Func<TSource, int>)这类),因此传入2个泛型参数时触发ArgumentException
可靠的筛选方案
直接通过泛型参数数量、参数类型的泛型定义精准定位目标重载,代码如下:
// 定位目标重载:Max<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>) var maxMethod = typeof(Enumerable).GetMethods() .Where(m => m.Name == "Max") // 筛选包含2个泛型参数的重载 .Where(m => m.GetGenericArguments().Length == 2) .Where(m => { var parameters = m.GetParameters(); // 确保方法有2个参数 if (parameters.Length != 2) return false; // 验证第一个参数是 IEnumerable<> 泛型类型 var firstParamType = parameters[0].ParameterType; if (!firstParamType.IsGenericType || firstParamType.GetGenericTypeDefinition() != typeof(IEnumerable<>)) return false; // 验证第二个参数是 Func<,> 泛型类型 var secondParamType = parameters[1].ParameterType; if (!secondParamType.IsGenericType || secondParamType.GetGenericTypeDefinition() != typeof(Func<,>)) return false; // 验证泛型参数匹配逻辑:第一个参数的泛型参数为TSource,第二个参数的泛型参数为TSource和TResult var methodGenericArgs = m.GetGenericArguments(); var tSource = methodGenericArgs[0]; var tResult = methodGenericArgs[1]; return firstParamType.GetGenericArguments()[0] == tSource && secondParamType.GetGenericArguments()[0] == tSource && secondParamType.GetGenericArguments()[1] == tResult; }) .First(); // 实例化泛型方法 var maxOfStringMethod = maxMethod.MakeGenericMethod(typeof(SomeViewModel), typeof(string));
简化方案(可选)
如果不需要动态指定泛型类型,尽量避免反射,直接使用静态调用或委托:
Func<IEnumerable<SomeViewModel>, Func<SomeViewModel, string>, string> maxFunc = Enumerable.Max;
内容的提问来源于stack exchange,提问作者Sarvesh Patil
相关产品推荐
相关产品推荐

