-1

我的构造函数将其实例解析为具有特定属性的事件:

_EventAttributes = from EventDescriptor a in TypeDescriptor.GetEvents(this)
            let attribute = a.Attributes[typeof(MyAttribute)] as MyAttribute
            where attribute != null
            select new EventAttributeTuple { Event = a, Attribute = attribute };

稍后在代码中,我想检查相应的事件是否为空(没有人对事件感兴趣)来决定是否必须将其写入我的 XML 输出:

//write events
foreach (var attr in _EventAttributes)
{
    if (check corresponding attr.Event object is null)
    {
        writer.WriteAttributeString(attr.Attribute.Name, GetRPCAdress(attr.Event.Name));
    }
}

编辑:

获取 EventInfo 也很容易:

var evtInfo = this.GetType().GetEvent(attr.Event.Name);

但是,我仍然不知道如何检查事件是否有订阅者。

编辑2:

用 dotPeek 查看生成的代码后,我认为这里没有机会访问任何字段:

    //original code
    [MyAttribute("onclick")]
    public event EventHandler<MouseArg> Click;

    //generated code
    [MyAttribute("onclick")]
    public event EventHandler<MouseArg> Click
    {
      add
      {
        EventHandler<MouseArg> eventHandler = this.Click;
        EventHandler<MouseArg> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<MouseArg>>(ref this.Click, comparand + value, comparand);
        }
        while (eventHandler != comparand);
      }
      remove
      {
        EventHandler<MouseArg> eventHandler = this.Click;
        EventHandler<MouseArg> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<MouseArg>>(ref this.Click, comparand - value, comparand);
        }
        while (eventHandler != comparand);
      }
    }

如果我自己处理所有事件添加/删除操作,可能会有机会,但这似乎很乏味。有人有更好的主意吗?

编辑3:

我明白了,我正在使用 this.GetType() 它没有给我声明类型,而是声明事件的类的子类,因此我无法检索该字段。

它现在是这样工作的:

var evtValue = attr.Event.ComponentType.GetField(attr.Event.Name, 
               BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);
4

1 回答 1

1

抱歉,这在一般情况下是不可能的,例如:

  class CounterExample {
    public event EventHandler MyEvent {
      add {
        // You can't control me here: whether I truly add an event or not 
        // and even if I always add the event - where I store it
      }
      remove {
        // You can't control me here: whether I truly remove an event or not
        // and even if I always remove the event - from where I delete it
      }
    }
  }

但在许多情况下,您可以进行 hack(不过要小心):

  class SimpleCase { 
    // Usual event realization (default add and remove accessors)
    public event EventHandler MyEvent; 
  }

  ...
  SimpleCase cs = new SimpleCase();
  cs.MyEvent += ...
  ...

  // Since MyEvent has default accessors, lets check the default storage: 
  FieldInfo fi = cs.GetType().GetField("MyEvent", BindingFlags.NonPublic | BindingFlags.Instance);
  Boolean myEventAssigned = !Object.ReferenceEquals(fi.GetValue(cs), null);
于 2013-06-28T17:18:24.600 回答