2

Say I have a console application or Windows service, and am using dependency injection with an IOC container (in my specific case, I'm using Autofac).

One of the classes that my IOC container resolves is a WorkDoer class, which has a long running DoWork(Args args) method. When DoWork(Args args) completes, a custom event is raised (WorkDone). In my case, DoWork is triggered as messages with parameters are taken off of a message queue.

I also have a Notifier class that I'd like to have subscribe to my WorkDone event.

Concretely

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.
        }
    }

So now I have my WorkDoer which is responsible for running some long running business logic and raises an event. Then I in theory have my Notifier that can listen for that event and run some logic decoupled from my business logic, such as pushing a notification to an MVC page in that solution, or maybe publishes another message queue message, or something like that.

The projects in my solution are

  • App.WorkerService -- this contains my WorkDoer console app and my DependencyConfig
  • App.BusinessLogic -- this is a library that contains all of the business logic that WorkDoer uses
  • App.Notification -- this is where I'd like my Notifier(s) to live

So here's my problem:

In my WorkerService Program.cs, I have my WorkDoer registered with Autofac's Single Instance Scope. This means that it's a transient instance and can disappear. As such, I'm not sure how I can subscribe to it's WorkDone event effectively in my Program.cs's Main method, since it will eventually get disposed of. I could make it use a singleton scope to avoid this, but then I've captured all of WorkDoer's dependencies within that long running scope, which I don't want to do.

I have my Notifier in a singleton scope so that I don't lose existing subscriptions -- I'm not sure if that's bad practice or not, and I'm happy to change it.

Basically, the big picture is that I want to have my business logic in a separate project than my notification logic to avoid leaking notification code into my business logic. I'd also like to have the ability to easily add/remove/change notifier types (SignalR, log file, MQ, etc.). I'd like to use the C# event and delegate system for this (seems reasonably relevant here), but I'm not sure how to manage my dependency scopes.

I did see this question but I'd like to avoid the suggestions of OnActivated or the delegate registration because of the aforementioned captured dependency concerns.

istrupin
  • 1,423
  • 16
  • 32

1 Answers1

2

Currently, you are using an observer design pattern for your notifications. You register the event handlers directly. That results in a tight coupling of the components.

For your requirements above, the publish/subscribe design pattern, using an event aggregator, would be better. The publisher and subscriber are only loosely coupled. Both know only the event aggregator. The event aggregator is injected into both and works as a mediator/facade/adapter.

There are many possible implementations. See:

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/

KBO
  • 653
  • 7
  • 17