【问题标题】:C# reflection, get overloaded methodC#反射,获取重载方法
【发布时间】:2017-06-15 13:35:49
【问题描述】:

我已经查看了其他一些关于反射和重载方法的帖子,但可以找到任何帮助。我发现的一篇帖子是this one,但这并没有太大帮助。

我有以下两种方法:

1 | public void Delete<T>(T obj) where T : class { ... }
2 | public void Delete<T>(ICollection<T> obj) where T : class { ... }

我正在尝试获取方法 N°1。

我尝试了经典的GetMethod("Delete") 方法,但由于有两种方法使用此名称,因此引发了Ambiguous-Exception。我尝试使用 GetMethod("Delete", new [] { typeof(Object) }) 之类的附加参数指定方法架构,但没有找到任何内容(返回 null)。

我想我不妨遍历所有方法并检查参数。

我写了下面的方法……

    public static IEnumerable<MethodInfo> GetMethods(this Type type, String name, Type schemaExclude)
    {
        IEnumerable<MethodInfo> m = type.GetRuntimeMethods().Where(x => x.Name.Equals(name));
        return (from r in m let p = r.GetParameters() where !p.Any(o => schemaExclude.IsAssignableFrom(o.ParameterType)) select r).ToList();
    }

...返回不包含schemaExclude类型参数的方法。

我这样称呼它 GetMethods("Delete", typeof(ICollection)) 没有按预期工作。

显然..ICollection'1[T] 不能分配给ICollectionIEnumerableIEnumerable&lt;&gt;ICollection&lt;&gt; 也不是。我再次尝试使用typeof(Object),它确实有效,但确实返回了两种方法(就像它应该的那样)。

我到底错过了什么?

【问题讨论】:

  • 当使用反射并要求具有特定类型参数的方法时,您不是要求具有 compatible 类型的方法,而是要求具有那些 参数的方法特定的类型。您希望在这方面支持的任何继承和接口实现都必须由您的代码处理。所以你要求一个带有ICollection参数的“删除”方法,但没有。
  • @LasseV.Karlsen 感谢您的评论。是的,这就是我想的。这就是为什么我在我编写的方法中采用了不同的方法,在该方法中我尝试检查应该排除的类型是否从参数类型中分配。这应该涵盖类的任何继承。你建议检查什么?对不同的方法有什么建议吗?
  • 编译时你知道T吗?例如,它只是GetMethods("Delete", typeof(ICollection&lt;int&gt;))。否则,您必须在前面使用 Type.MakeGenericType 构建运行时类型。
  • @HimBromBeere 在编译时?不。我将它用于基于实体框架的非常通用的数据操作方法。 T 可以是我的域支持的任何型号。我正在处理的对象是一个代理对象,这意味着我不得不使用反射来访问具有正确泛型类型的方法。我可以尝试在运行时构建泛型类型以获得ICollection&lt;T&gt;,但我不确定这是否与方法的架构匹配。让我试试……
  • @HimBromBeere 我用typeof(ICollection&lt;&gt;).MakeGenericType(t) 尝试过,其中 t 等于实体框架模型类型。我的方法作为结果返回了这两种方法,这意味着它与架构不匹配。

标签: c# generics reflection overloading generic-list


【解决方案1】:

您可以通过检查其泛型参数类型来查找该方法,如下所示:

return type
    .GetRuntimeMethods()
    .Where(x => x.Name.Equals("Delete"))
    .Select(m => new {
         Method = m
    ,   Parameters = m.GetParameters()
    })
    .FirstOrDefault(p =>
        p.Parameters.Length == 1
    &&  p.Parameters[0].ParameterType.IsGenericType
    &&  p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(ICollection<>)
    )?.Method;

符合以下条件的上述过滤方法:

  • 称为“删除”,
  • 使用单个参数,
  • 参数为泛型,
  • 使用从ICollection&lt;&gt; 构造的泛型参数类型

Demo.

【讨论】:

  • 感谢您的回答!这确实解决了我的问题,尽管我真正需要的只是你的演示中的 ParameterType.IsGenericType 部分。我将支票更改为 schemaExclude.IsAssignableFrom(o.ParameterType.IsGenericType ? o.ParameterType.GetGenericTypeDefinition() : o.ParameterType) 。成功了
猜你喜欢
  • 2012-10-04
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2014-12-31
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多