使用具有IOC容器的委托和事件时避免强制依赖性

时间:2018-04-05 00:03:41

标签: c# events dependency-injection delegates autofac

假设我有一个控制台应用程序或Windows服务,并且正在使用IOC容器的依赖注入(在我的特定情况下,我正在使用Autofac)。

我的IOC容器解析的一个类是WorkDoer类,它具有长时间运行的DoWork(Args args)方法。当DoWork(Args args)完成时,会引发自定义事件(WorkDone)。在我的例子中,DoWork被触发,因为带有参数的消息将从消息队列中删除。

我还有一个Notifier类,我想订阅我的WorkDone事件。

具体地

public class Notifier
    {
        public void Subscribe(WorkDoer w)
        {
            w.WorkDone += new WorkDoer.WorkDoneHandler(Notify);
        }
        private void Notify(WorkDoer w, EventArgs e)
        {
            //do some kind of notification decoupled from my WorkDoer
            //concretely I'd like to push a SignalR message or something.
        }
    }

所以现在我的WorkDoer负责运行一些长时间运行的业务逻辑并引发一个事件。然后我理论上我的Notifier可以监听该事件并运行一些与我的业务逻辑分离的逻辑,例如将通知推送到该解决方案中的MVC页面,或者可能发布另一个消息队列消息,或类似的东西。 / p>

我的解决方案中的项目是

  • App.WorkerService - 包含我的WorkDoer控制台应用程序和我的DependencyConfig
  • App.BusinessLogic - 这是一个包含WorkDoer使用的所有业务逻辑的库
  • App.Notification - 这是我希望我的通知器生效的地方

所以这是我的问题:

在我的WorkerService Program.cs中,我的WorkDoer已在Autofac的Single Instance Scope中注册。这意味着它是一个瞬态实例并且可以消失。因此,我不确定如何在Program.cs的Main方法中有效地订阅它的WorkDone事件,因为它最终会被处理掉。我可以使用单例范围来避免这种情况,但后来我已经捕获了长期运行范围内的所有WorkDoer依赖项,我不想这样做。

我将Notifier放在单一范围内,这样我就不会丢失现有的订阅 - 我不确定这是不是很糟糕,我很乐意改变它。

基本上,大局是我希望将我的业务逻辑放在一个单独的项目而不是我的通知逻辑中,以避免将通知代码泄漏到我的业务逻辑中。我还希望能够轻松添加/删除/更改通知程序类型(SignalR,日志文件,MQ等)。我想使用C#事件和委托系统(这里似乎相当合理),但我不知道如何管理我的依赖范围。

我确实看到了this question,但我想避免OnActivated或委托注册的建议,因为上述捕获的依赖关系问题。

1 个答案:

答案 0 :(得分:2)

目前,您正在使用观察者设计模式进行通知。您直接注册事件处理程序。这导致组件的紧密耦合。

根据您的要求,使用事件聚合器的发布/订阅设计模式会更好。发布者和订阅者只是松散耦合。两者都只知道事件聚合器。事件聚合器被注入到两者中,并作为中介/外观/适配器。

有许多可能的实现。参见:

https://www.codeproject.com/Articles/812461/Event-Aggregator-Pattern

https://www.martinfowler.com/eaaDev/EventAggregator.html

https://www.c-sharpcorner.com/UploadFile/pranayamr/publisher-or-subscriber-pattern-with-event-or-delegate-and-e/