Dav*_*ave 26 .net c# generics reflection
我想得到方法System.Linq.Queryable.OrderyBy<T, TKey>(the IQueryable<T> source, Expression<Func<T,TKey>> keySelector)方法,但我不断提出空值.
var type = typeof(T);
var propertyInfo = type.GetProperty(group.PropertyName);
var propertyType = propertyInfo.PropertyType;
var sorterType = typeof(Func<,>).MakeGenericType(type, propertyType);
var expressionType = typeof(Expression<>).MakeGenericType(sorterType);
var queryType = typeof(IQueryable<T>);
var orderBy = typeof(System.Linq.Queryable).GetMethod("OrderBy", new[] { queryType, expressionType }); /// is always null.
Run Code Online (Sandbox Code Playgroud)
有没有人有任何见解?我宁愿不循环GetMethods结果.
Nei*_*eil 21
解决了(通过黑客攻击LINQ)!
我在研究同样的问题时看到了你的问题.在找不到好的解决方案之后,我有了查看LINQ表达式树的想法.这是我想出的:
public static MethodInfo GetOrderByMethod<TElement, TSortKey>()
{
Func<TElement, TSortKey> fakeKeySelector = element => default(TSortKey);
Expression<Func<IEnumerable<TElement>, IOrderedEnumerable<TElement>>> lamda
= list => list.OrderBy(fakeKeySelector);
return (lamda.Body as MethodCallExpression).Method;
}
static void Main(string[] args)
{
List<int> ints = new List<int>() { 9, 10, 3 };
MethodInfo mi = GetOrderByMethod<int, string>();
Func<int,string> keySelector = i => i.ToString();
IEnumerable<int> sortedList = mi.Invoke(null, new object[] { ints,
keySelector }
) as IEnumerable<int>;
foreach (int i in sortedList)
{
Console.WriteLine(i);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:10 3 9
编辑:如果你在编译时不知道类型,这里是如何获取方法:
public static MethodInfo GetOrderByMethod(Type elementType, Type sortKeyType)
{
MethodInfo mi = typeof(Program).GetMethod("GetOrderByMethod", Type.EmptyTypes);
var getOrderByMethod = mi.MakeGenericMethod(new Type[] { elementType,
sortKeyType });
return getOrderByMethod.Invoke(null, new object[] { }) as MethodInfo;
}
Run Code Online (Sandbox Code Playgroud)
一定要用typeof(WhateverClassYouDeclareTheseMethodsIn)替换typeof(Program).
Jon*_*eet 13
作为扩展方法的解决方案的变体:
public static class TypeExtensions
{
private static readonly Func<MethodInfo, IEnumerable<Type>> ParameterTypeProjection =
method => method.GetParameters()
.Select(p => p.ParameterType.GetGenericTypeDefinition());
public static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
{
return (from method in type.GetMethods()
where method.Name == name
where parameterTypes.SequenceEqual(ParameterTypeProjection(method))
select method).SingleOrDefault();
}
}
Run Code Online (Sandbox Code Playgroud)
今天有一个很好的替代方法Type.MakeGenericMethodParameter。以下代码片段检索该Queryable.OrderBy方法:
var TSource = Type.MakeGenericMethodParameter(0);
var TKey = Type.MakeGenericMethodParameter(1);
var orderBy = typeof(Queryable).GetMethod(nameof(Queryable.OrderBy), 2, BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard
, new[] { typeof(IQueryable<>).MakeGenericType(TSource), typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(TSource, TKey)) }
, null);
Assert.NotNull(orderBy);
Run Code Online (Sandbox Code Playgroud)
小智 5
我认为以下扩展方法可以解决该问题:
public static MethodInfo GetGenericMethod(
this Type type, string name, Type[] generic_type_args, Type[] param_types, bool complain = true)
{
foreach (MethodInfo m in type.GetMethods())
if (m.Name == name)
{
ParameterInfo[] pa = m.GetParameters();
if (pa.Length == param_types.Length)
{
MethodInfo c = m.MakeGenericMethod(generic_type_args);
if (c.GetParameters().Select(p => p.ParameterType).SequenceEqual(param_types))
return c;
}
}
if (complain)
throw new Exception("Could not find a method matching the signature " + type + "." + name +
"<" + String.Join(", ", generic_type_args.AsEnumerable()) + ">" +
"(" + String.Join(", ", param_types.AsEnumerable()) + ").");
return null;
}
Run Code Online (Sandbox Code Playgroud)
该调用将类似于(仅更改原始代码的最后一行):
var type = typeof(T);
var propertyInfo = type.GetProperty(group.PropertyName);
var propertyType = propertyInfo.PropertyType;
var sorterType = typeof(Func<,>).MakeGenericType(type, propertyType);
var expressionType = typeof(Expression<>).MakeGenericType(sorterType);
var queryType = typeof(IQueryable<T>);
var orderBy = typeof(Queryable).GetGenericMethod("OrderBy",
new Type[] { type, propertyType },
new[] { queryType, expressionType });
Run Code Online (Sandbox Code Playgroud)
与其他解决方案的不同之处在于:生成的方法与参数类型完全匹配,而不仅仅是它们的通用基本类型。
| 归档时间: |
|
| 查看次数: |
12859 次 |
| 最近记录: |