事件订阅者是否应该始终注册事件处理程序,或者其他类是否可以执行此操作?
示例:
{{1}}
答案 0 :(得分:0)
事件订阅者是否应始终注册事件处理程序,或者是 另一个班级可以做到吗?
这个设计本身并没有什么本质上的错误,但它实际上取决于你的架构以及你想要它的可扩展性和分离性。
请注意,没有与Glue
提出的通用假设的背景信息,因此很难说清楚您的确切要求。
...
现在,我很少编写传统事件,并倾向于使用更现代的Pub / Sub Producer / Consumer Decoupled Messages 或Event Aggregator方法(取决于您使用的框架) )。消费者可以随意订阅,生产者可以随意发布,而无需事先了解彼此。 Martin Follower在他的网站上更详细地介绍了这种模式。
更重要的是,分离消息(和亲属)的优势在于,消费者可以订阅对话,而无需事先知道生产者是谁,这样可以更好地decoupling,从而创造更多可维护和可扩展的系统。如果系统变得足够大,将类推送到Microservices可能会少得多痛苦。
说这个,如果这只是一个非常简单的实现(和紧密耦合的实现),标准的香草冰淇淋风味的.NET事件并让你的订阅者注册事件处理程序没有任何问题,尽管你必须再次将此分解为您设计中最合乎逻辑的问题。
我应该让SoundManager知道一只狗及其树皮。或者你的狗类应该注册给声音管理员。你的设计直觉应该引领方式
无论如何,祝你好运。
答案 1 :(得分:0)
程序化,没有错,会为你顺利工作。
事实上,你需要在EventSubscriber
方法的情况下这样做
(Handler
)应在Event
上调用,不具有EventPublisher
类的对象。
如何订阅事件是主观的事情,它取决于你的所有流量和舒适度。
但据我所知,订阅者类订阅活动使代码更具可读性和易于理解
你看到订阅任何类的事件,订阅者类必须有该类的对象,但在你的例子中它没有。
一般来说,当订阅者类本身拥有发布者类的对象时,人们会以这种方法设计体系结构。这种设计在某些流程中有其自身的优点,请参见下面的示例
public class EventPublisher
{
public event EventHandler HeavyLogicDone;
public void ExposedMethod(string subScriberSpecificData)
{
Thread logicCaller = new Thread(() => HeavyLogic(subScriberSpecificData));
logicCaller.Start();
}
private void HeavyLogic(string subScriberSpecificData)
{
//logic which may take time
if (HeavyLogicDone != null)
HeavyLogicDone(this, new EventArgsClass(subScriberSpecificData));
}
}
此处EventPublisher
类具有公开的功能,应该由EventSubscriber
调用,但由于此方法可能需要一些时间,因此它是用线程编写的。
现在问题,因为它在线程中,这个方法的调用将在启动线程后很快返回,订阅者无法启动其依赖于此方法的结果的功能,它必须等待。因此,要通知订阅者已完成任务,则会发生一个事件。
public class EventSubscriber
{
string currentData = "";
public EventSubscriber(EventPublisher eventPublisher, string data)
{
currentData = data;
eventPublisher.HeavyLogicDone += eventPublisher_HeavyLogicDone;
eventPublisher.ExposedMethod(currentData);
//Contineous without waiting for heavy logic to compelete
}
void eventPublisher_HeavyLogicDone(object sender, EventArgs e)
{
if(((EventArgsData)e).subScriberSpecificData == currentData)
{
//Do further task which is dependant to result of logic
//if now subscriber doesn't need to listen this event anymore
((EventPublisher)sender).HeavyLogicDone -= eventPublisher_HeavyLogicDone;
}
}
}
正如您所知,何时订阅某个活动以及何时取消订阅,订阅者现在可以完全控制。
但是,如果你这样做的话。
static void Main(string[] args)
{
EventSubscriber subscriber1 = new EventSubscriber("sub1");
EventSubscriber subscriber2 = new EventSubscriber("sub2");
EventPublisher pub = new EventPublisher();
pub.HeavyLogicDone += subscriber1.eventPublisher_HeavyLogicDone;
pub.HeavyLogicDone += subscriber2.eventPublisher_HeavyLogicDone;
pub.ExposedMethod("sub1");
pub.ExposedMethod("sub2");
}
第一个问题:正如您所看到的,每次创建Subscriber实例时,您都必须明确地为其订阅并为当前订阅者调用发布者的方法。这是耦合代码,你需要每次都这样做。
和订阅者类
public class EventSubscriber
{
string currentData = "";
public EventSubscriber(string data)
{
currentData = data;
}
public void eventPublisher_HeavyLogicDone(object sender, EventArgs e)
{
if(((EventArgsData)e).subScriberSpecificData == currentData)
{
//Do further task which is dependant to result of logic
//if now subscriber doesn't need to listen this event anymore
((EventPublisher)sender).HeavyLogicDone -= eventPublisher_HeavyLogicDone;
}
}
}
第二个问题:由于订阅不能控制订阅者类,因此只能使用订阅者类进行取消订阅。代码将很难理解。