Class Library Event Aggregator instead of Logging - c#

I'm writing a class library and I'm wondering how I can pass messages to the consumer application for logging purposes. For Exceptions I plan to create custom Exceptions and throw them. But what's about information logging? Like: "Connecting successful".
I had the idea to implement some sort of event aggregator in my library and allow the consumer app to subscribe to certain events. Then the consumer app can decide if the want to log information or not.
Is this good practice? I just think Logging shouldn't be part of the library's responsibility.
Or are there any other ways to pass logging information to the user?

Related

Are C# events feasible for domain events in DDD? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I read that people use event dispatching libraries for domain events in their domain-driven design.
The C# language have built-in support for events using the event keyword together with the EventHandler<> class. Is it feasible to use this instead of a event dispatcher library (such as MediatR)?
I know that domain events are often dispatched when persisted, not when the method on the aggregate is called. But by adding the events to a List<Action> you can defer the raising of events.
Event declaration:
public event EventHandler<InvoiceCreatedEventArgs> InvoiceCreated;
Deferred event raising:
private ICollection<Action> _events = new List<Action>();
public void AddDomainEvent(Action action)
{
_events.Add(action);
}
protected virtual void OnInvoiceCreated(InvoiceCreatedEventArgs e)
{
AddDomainEvent(() => { InvoiceCreated?.Invoke(this, e); });
}
If the events are exposed as public members of the root aggregate then the application would have to resubscribe for every new instance of the root aggregate whenever a root aggregate was fetched from the repository.
Wouldn't that be a bit of a undesirable trait to have to resubscribe for every instance? Would the application have to unsubscribe too?
Unless the events were declared as static, but I have heard bad things about static events and memory leaks. Would this be a concern?
If C# events were used, would they belong in the root aggregate or would they belong in the repository?
If the events were declared in the repository (which could be a Entity Framework Core DbContext) then when registered with the ASP.NET Core dependency handler using the .AddDbContext method it would be registered with the "Scoped" lifetime (once per client request), so unless the events were to be declared as static then the application would have to resubscribe on every new instance of the repository which would occur at every new incoming HTTP request.
Is using C# events for domain events in a application employing domain-driven design feasible or is it just an non-viable ill-fated idea?
Without distinguishing between C# Events and Domain Events it’s difficult to follow your narrative. However, if I understand your proposal correctly, you’re envisioning a C# component that listens to the Entity Event stream, then publishes those incoming domain events via C# events to listeners in the app. If that’s what you’re proposing then you would have to work hard to make it work, and it wouldn’t work well.
If we look at Mediatr, it subscribes to an event source and creates new command processors to process incoming domain events. The key is that it creates new command processors so it is able to call a method on them. Also, there is a one-to-one correspondence between a domain event and a command processor, and nothing is required at system startup other than Mediatr itself.
With C# Events the command processor is created by something, then registers itself to receive C# events of a particular type. The command processor initiates the link, not the event source subscriber. In order to process all kinds of events, at startup you would have to create at least one of each type of command processor and let it register itself as the receiver of the C# messages which carries the Domain Event as a payload.
Then what happens when you start to scale? Mediatr scales well because it creates a command processor for each Domain Event. Your proposal would not scale because to process 2 of the same event type you would need to manually create 2 command processors, and each of those command processors would receive BOTH of the incoming Domain Events because they are both subscribed to the same C# Event.
It is possible to code around all this mess, but that’s what Jimmy Bogard has already done. Instead of rewriting all that just fire up NuGet, pull down Mediatr, and then go play with your kids with all the time you saved.
It depends on the type of application.
If the application is a web application then it have a DbContext scoped to the life time of the HTTP request, and all the aggregates have a short life time too that lasts for the duration of the HTTP request. Hence registering the C# event handlers is cumbersome, also since you would have to do it after you fetch get the DbContext or the aggregate it would have to be inside the controller, repeatedly, everywhere. So for web applications using C# for events is a poor choice, and it a much better idea to delegate it to a singleton class as is done with MediatR.
If the application maintains a persistent DbContext that survives for the lifetime of the application and a root aggregate that survives for the lifetime of the application then you can could use C# events and just register the event handlers once. Such an application could be a command-line application, a background service, or a desktop application with a UI.

Avoiding captive dependencies when using delegates and events with an IOC Container

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

architecture for bubbling events through classes hierarchy

I have a simple application that consists of a console application and a class library. The class library does all of the heavy lifting throughout its few-dozen classes. Some of those classes are internal to the class library, and even if public, I'd rather not have the console application completely aware of them.
So I could have something like:
My Program.cs class that is running.
My DoSomething.cs class that is being called by Program.cs.
My DoSomethingInParticular.cs class that is being called by DoSomething.cs
And so on, and so on.
Is there a generally understood way of letting Program.cs be aware of lower changes?
Functionally I'd like to have my console application write out lower level events to the console window, which is where I'm trying to go with this.
A module only knows as much as it knows.
I see 2.1 main paths for you.
1) Make public events in DoSomething that Program can listen to.
Make public events in DoSomethingInParticular that DoSomething can listen to.
When DoSomething receives an event it decides if it is proper for bubbling and transforms it to one event of its own and raises it for Program to receive.
1.1) Put the data carrying structures/classes in the events in another, common, lib. Then when an event is received DoSomething doesn't have to transform it but only decide whether to bubble it or not.
2) Make an event handling lib of its own to handle who receives what.
Without knowing more I would go with 1.1.
HTH

How to create an async/background process within a WCF operation?

In my WCF operations I will do the logic necessary for the operation: save a record, get a dataset, etc. and in some cases I need to log the activity as well. However, in these cases I feel that there is no point in having the client application waiting for the WCF operation to log the activity. I would like to fire off the logging process and then immediately return whatever necessary to the client without waiting for the logging process to complete.
I do not care to know when the logging process is complete, just fire and forget.
I also prefer to use BasicHttpBinding to maintain maximum interoperability.
Is this possible? Would anyone care sharing coding samples or links to sites with coding examples?
This can be accomplished pretty easily using any number of threading techniques.
For a very simple example, try modifying this:
// Log something going on.
System.Threading.ThreadPool.QueueUserWorkItem((args) =>
{
System.Diagnostics.EventLog.WriteEntry("my source", "my logging message");
});
Inside that lambda method you can use whatever logging class you prefer, and you can include local variables to the logger if you want to log some current state.

Application.ThreadException on WCF Service?

I can´t find a Application.ThreadException event to listen to on my WCF service. I suppose that this is for WinForms so is there a ThreadException event for WCF services? Or will they end up in AppDomain.CurrentDomain.UnhandledException?
The Application.ThreadException event is only used to "to handle otherwise unhandled exceptions that occur in Windows Forms thread" (emphasis added, MSDN), so it isn't of much help in a WCF service.
Your best bet is to indeed use AppDomain.CurrentDomain.UnhandledException. Note however, that you cannot prevent the process from exiting. This event merely allows you to do some logging or error reporting, before "the system default handler reports the exception to the user and terminates the application." (MSDN).
You many also want to implement your own IErrorHandler. Also, checkout this blog entry about some WCF error handling best practices, while your at it.
It looks like you'll need to implement IErrorHandler:
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx
Then register your handler with your ServiceHost:
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.channeldispatcher.errorhandlers.aspx
It looks like you can also wire up the IErrorHandlers using a custom attribute as described here: http://msdn.microsoft.com/en-us/library/ms751439.aspx
It depends on your client framework.
WCF faults get thrown as exceptions on the client side, so handle them like any other global exception handler:
Winforms uses
Application.ThreadException
WPF uses:
Application.DispatcherUnhandledException
As Christian states, these are only for exceptions thrown on the "GUI" thread, but WCF will marshal callbacks on a duplex service to these by default I think.

Categories