c# - 如何通过反射忽略父接口(interface)上的事件来获取类型的事件

标签 c# events reflection interface

我有以下代码

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

然而,这也返回了我声明的事件 父接口(interface)。例如

两者

UIElement
ContentElement

实现

IInputElement

定义事件

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

但是上面对 GetEvents 的所有绑定(bind)标志设置如上 返回接口(interface)事件以及两个具体类。

如何从中过滤掉在父接口(interface)上定义的事件 获取事件?

请注意,我正在为每个事件生成扩展方法,就像这样

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

所以我只做了事件的根定义,没有派生虚拟或接口(interface)实现。

最佳答案

在例子中:

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) 上使用反射,您想查看哪个事件?

回答:

你可以使用类似的东西:

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

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

编辑以回答

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

此添加可确保我也获得接口(interface)。

替代方法:

要确定一个成员是否实现了某个接口(interface),可以使用这个:

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() 结合使用。

关于c# - 如何通过反射忽略父接口(interface)上的事件来获取类型的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15895091/

相关文章:

c# - 使用 SqlDataReader 将 DateTime2 转换为 C# DateTime

javascript - jquery 关闭未被触发

excel - 隐藏选定单元格中的公式

java - 需要在反射(reflection)时弄脏我的手

c# - 如何将依赖项注入(inject)动态加载的程序集

c# - 在运行空间中从 c# 调用 PowerShell 脚本并获取发生错误的行号

c# - ORA-00933: SQL 命令未正确结束

c# - .Net 核心中 Json() 的小写属性名称

javascript - "this"在backbone的listenTo()中指的是什么

java - 查找接口(interface)的所有实现,包括 lambda