在运行时使用反射检查是否订阅了给定事件
考虑一个有一些事件的类。该事件列表将会不断增长。有些是可选的。其他的都是需要的。
为了简化一些初始验证,我有一个自定义属性,将事件标记为必需事件。 例如:
[RequiredEventSubscription("This event is required!")]
public event EventHandler ServiceStarted;
到目前为止一切顺利。 为了验证所有事件,我使用反射迭代事件列表并获取自定义属性。 但我需要一种方法来确定该事件是否已订阅。
无需反射,ServiceStarted.GetInitationList 即可完成这项工作。但该事件必须来自此列表: var eventList = this.GetType().GetEvents().ToList();
有没有办法检查事件列表中的给定事件是否使用反射订阅?
- [更新] - 这是基于 Ami 的回答的一个可能的解决方案:
private void CheckIfRequiredEventsAreSubscribed()
{
var eventList = GetType().GetEvents().ToList().Where(e => Attribute.IsDefined(e, typeof(RequiredEventSubscription)));
StringBuilder exceptionMessage = new StringBuilder();
StringBuilder warnMessage = new StringBuilder();
foreach (var evt in eventList)
{
RequiredEventSubscription reqAttr = (RequiredEventSubscription) evt.GetCustomAttributes(typeof(RequiredEventSubscription), true).First();
var evtDelegate = this.GetType().GetField(evt.Name, BindingFlags.Instance | BindingFlags.NonPublic);
if (evtDelegate.GetValue(this) == null)
{
warnMessage.AppendLine(reqAttr.warnMess);
if (reqAttr.throwException) exceptionMessage.AppendLine(reqAttr.warnMess);
}
}
if (warnMessage.Length > 0)
Console.WriteLine(warnMessage);
if (exceptionMessage.Length > 0)
throw new RequiredEventSubscriptionException(exceptionMessage.ToString());
}
非常感谢!
Consider a class that has some events. This event list is going to grow. Some are optional. Others are required.
To simplify some initial validation I have a custom attribute that marks an event as a required one.
For example:
[RequiredEventSubscription("This event is required!")]
public event EventHandler ServiceStarted;
So far so good.
To validate all events, using reflection I iterate the event list and grab the custom attributes.
But I need a way to determine if the event is subscribed or not.
Without reflection the ServiceStarted.GetInvocationList does the job. But the event must come from this list:
var eventList = this.GetType().GetEvents().ToList();
Is there any way to check if a given event, from an event list, is subscribed using reflection?
--[Update]--
Here's a possible solution based on Ami's answer:
private void CheckIfRequiredEventsAreSubscribed()
{
var eventList = GetType().GetEvents().ToList().Where(e => Attribute.IsDefined(e, typeof(RequiredEventSubscription)));
StringBuilder exceptionMessage = new StringBuilder();
StringBuilder warnMessage = new StringBuilder();
foreach (var evt in eventList)
{
RequiredEventSubscription reqAttr = (RequiredEventSubscription) evt.GetCustomAttributes(typeof(RequiredEventSubscription), true).First();
var evtDelegate = this.GetType().GetField(evt.Name, BindingFlags.Instance | BindingFlags.NonPublic);
if (evtDelegate.GetValue(this) == null)
{
warnMessage.AppendLine(reqAttr.warnMess);
if (reqAttr.throwException) exceptionMessage.AppendLine(reqAttr.warnMess);
}
}
if (warnMessage.Length > 0)
Console.WriteLine(warnMessage);
if (exceptionMessage.Length > 0)
throw new RequiredEventSubscriptionException(exceptionMessage.ToString());
}
Many thanks!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里存在一些主要的设计问题。一般来说,无法询问对象其事件的订阅者是谁。任何人都想要这个功能是非常不寻常的,但如果你真的想要它,你应该让类以某种方式公开它,例如,通过使用如下方法实现接口:
无论如何,要回答所提出的问题,你< em>可以使用反射,但前提是您确切地知道订阅者是如何维护的。例如,
假设所有事件都是使用当前的 C# 类字段事件实现来实现的,您可以执行类似的操作(强烈不鼓励):
There are some major design issues here. In general, there's no way to ask an object who its events' subscribers are. It's highly unusual that anyone would want this functionality, but if you really want it, you should get classes to somehow expose this, for example, by implementing an interface with a method such as:
Anyway, to answer the question as asked, you can use reflection, but only if you know exactly how the subscribers are being maintained. For example,
assuming that all events are implemented with the current implementation of C# field-like events, you can do something like (strongly discouraged):