如何通过反射忽略父接口上的事件来获取类型的事件 [英] How to get events of type by reflection ignoring events on parent interfaces

查看:115
本文介绍了如何通过反射忽略父接口上的事件来获取类型的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码

Type type = ...
var events=type.GetEvents(
    BindingFlags.DeclaredOnly 
    | BindingFlags.Instance 
    | BindingFlags.Public).ToList(); 

然而,这也是我在
父接口上声明的事件。例如

However this is also returning me events declared on parent interfaces. For example

两者

UIElement
ContentElement

工具

IInputElement

定义事件

//
// Summary:
//     Occurs when the mouse pointer moves while the mouse pointer is over the element.
event MouseEventHandler PreviewMouseMove;

但上面调用GetEvents且所有绑定标志设置如上
都会返回事件对于接口以及两个具体类。

but the above call to GetEvents with all the binding flags set as above returns the event for the interface as well as the two concrete classes.

如何从
GetEvents中过滤掉父接口上定义的事件?

How can I filter out events that are defined on parent interfaces from GetEvents?

请注意,我为每个事件生成扩展方法,如此

Note that I am generating extensions methods for each event like so

public static 
IObservable<EventPattern<MouseButtonEventArgs>> 
PreviewMouseLeftButtonDownObserver(this IInputElement This){
        return Observable
               .FromEventPattern
               <MouseButtonEventHandler, MouseButtonEventArgs>
               ( h => This.PreviewMouseLeftButtonDown += h
               , h => This.PreviewMouseLeftButtonDown -= h);
}

所以我只做了事件的根定义而不是派生的虚拟或接口实现。

so I only did the root definition of the event not derived virtual or interface implementations.

推荐答案

在示例中:

interface IFace
{
    event EventHandler A;
}

class Base
{
    public virtual event EventHandler B;

    public event EventHandler C;
}

class YourType : Base, IFace
{
    public event EventHandler A;          // implements interface

    public override event EventHandler B; // overrides base class implementation

    public event EventHandler D;          // new event
}

如果使用反射,您希望看到哪个事件? typeof(YourType)

which event do you want to see if you use reflection on typeof(YourType)?

答案:

您可以使用以下内容:

events.Where(x =>
  x.GetAddMethod().GetBaseDefinition().DeclaringType == type
  && !x.GetAddMethod().IsFinal)
  );

其中类型就像你的问题一样。第一个标准确保它不是在父类型上定义的事件。第二个标准确保它不是接口实现。您可能不需要第二个标准,具体取决于您的确切设置。

where type is like in your question. The first criterion makes sure it is not an event defined on a parent type. The second criterion makes sure it's not an interface implementation. You might not need the second criterion, depending on your exact setup.

编辑到答案

events.Where(x =>{ 
   var addMethod = x.GetAddMethod();
   var basetype = addMethod.GetBaseDefinition().DeclaringType;
   return basetype == type && (!addMethod.IsFinal || basetype.IsInterface);
}) 

此添加确保我也可以获得接口。

This addition ensures that I get the interfaces as well.

替代方法

为了明确确定某个成员是否实现某个接口,可以使用:

To definitely determine if a member implements some interface or not, one can use this:

var interfaceImplementingMethods = new HashSet<MethodInfo>(type.GetInterfaces()
  .SelectMany(i => type.GetInterfaceMap(i).TargetMethods));
var result = events.Where(x => !interfaceImplementingMethods
  .Contains(x.GetAddMethod()));

即使执行成员被声明为 virtual (或 abstract )。如果你想排除继承的成员,这必须与 GetBaseDefinition()结合使用。

It should work even if the implementing member is declared virtual (or abstract). This must be combined with GetBaseDefinition() if you want to exclude also inherited members, of course.

这篇关于如何通过反射忽略父接口上的事件来获取类型的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆