首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何获取MethodInfo for Enumerable.SequenceEqual

如何获取MethodInfo for Enumerable.SequenceEqual
EN

Stack Overflow用户
提问于 2015-09-25 07:00:10
回答 3查看 702关注 0票数 4

我正在尝试使用MethodInfoEnumerable.SequenceEqual获取Type.GetMethod(...)。到目前为止,我已经尝试了以下几点:

代码语言:javascript
复制
var mi = typeof(Enumerable).GetMethod(nameof(Enumerable.SequenceEqual),
    BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Any,
    new Type[] { typeof(IEnumerable<>), typeof(IEnumerable<>) }, null);

代码语言:javascript
复制
var enumTyped = typeof(IEnumerable<>).MakeGenericType(ValueType);
var mi = typeof(Enumerable).GetMethod(nameof(Enumerable.SequenceEqual),
    BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Any,
    new Type[] { enumTyped, enumTyped }, null);

但是,这两种解决方案都返回null,而不是我想要的方法。我知道可以通过调用GetMethods()和筛选来检索该方法,但我非常想知道如何使用GetMethod(...)检索它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-25 07:48:08

不幸的是,为了使用Type.GetMethod(string name, Type[] types)获得泛型方法,必须在Type[]中提供正确的泛型类型,这意味着当您尝试这样做时:

代码语言:javascript
复制
Type requiredType = typeof(IEnumerable<>);
typeof(Enumerable).GetMethod("SequenceEqual", new Type[] { requiredType, requiredType });

你真的需要这样做:

代码语言:javascript
复制
Type requiredType = typeof(IEnumerable<TSource>);
typeof(Enumerable).GetMethod("SequenceEqual", new Type[] { requiredType, requiredType });

因为如果您查看SequenceEqual的签名,一般类型是IEnumerable<TSource>而不是IEnumerable<>

代码语言:javascript
复制
public static IEnumerable<TSource> SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);

但是:您无法访问TSource类型,以便使用它。因此,获得IEnumerable<TSource>的唯一方法是使用反射,如下所示:

代码语言:javascript
复制
MethodInfo info = typeof(Enumerable)
    .GetMethods(BindingFlags.Static | BindingFlags.Public)
    .Where(x => x.Name.Contains("SequenceEqual"))
    .Single(x => x.GetParameters().Length == 2);
Type genericType = typeof(IEnumerable<>).MakeGenericType(infos.GetGenericArguments());

而不是让方法

代码语言:javascript
复制
typeof(Enumerable).GetMethod("SequenceEqual", new Type[] { genericType, genericType });

但这要求我们无论如何都要获得SequenceEqual 方法(),因此可悲的事实是,当使用GetMethod而不是GetMethods的重载很少时,该方法实际上是不可能的*(您可以实现Binder,并在GetMethod方法中使用它,但是它将需要非常长的编码,这可能是错误和不可维护的,应该避免)。

票数 3
EN

Stack Overflow用户

发布于 2015-09-25 07:58:38

想要添加到以前的答案一点。首先,确实不可能使用单个GetMethod来做您想做的事情。但是,如果不想调用GetMethods并获取可枚举的所有180+方法,则可以这样做:

代码语言:javascript
复制
var mi = typeof(Enumerable).GetMember(nameof(Enumerable.SequenceEqual), MemberTypes.Method,
            BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod).OfType<MethodInfo>().ToArray();

GetMember调用将只返回两个重载的SequenceEqual方法,您可以选择其中一个并执行MakeGenericMethod,如其他答案所示。此外,根据您的目标,您可以考虑使用表达式:

代码语言:javascript
复制
var source = Expression.Parameter(
            typeof(IEnumerable<string>), "source");
var target = Expression.Parameter(
            typeof(IEnumerable<string>), "target");
var callExp = Expression.Call(typeof(Enumerable), "SequenceEqual", new Type[] { typeof(string)},
            source, target);            
var lambda = Expression.Lambda<Func<IEnumerable<string>, IEnumerable<string>, bool>>(callExp, source, target).Compile();
var result = lambda(new[] { "1", "2", "3" }, new[] { "1", "2", "3" });
Debug.Assert(result);
票数 2
EN

Stack Overflow用户

发布于 2020-07-15 11:54:41

另一个有一点不同的答案,基于以前的两个答案,但使用的是MakeGenericMethod调用和VisualBasic版本。

代码语言:javascript
复制
Dim lSequanceEqual As MethodInfo = GetType(System.Linq.Enumerable).GetMethods()
    .First(Function(mi) mi.Name.Contains(NameOf(System.Linq.Enumerable.SequenceEqual)) AndAlso mi.GetParameters.Length = 2)
Dim lMethod As MethodInfo = lSequanceEqual.MakeGenericMethod(New Type() { GetType(String)}) 
if CBool(lMethod.Invoke(Nothing, New Object() { firstList, secondList})) Then 'Do something
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32776542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档