I was working on migrating over a project which uses a static logger, and a static email service.
The email service logs emails sent, and the logger service sends an email if there are any logging issues (like DB down, etc.). If the email service fails, it can also log the issue.
If the logger fails, it tries to send an email notice, but if the email service fails (which could be why the logger was called in the first place), it just continues on and writes the issue to a log file.
Email Service <--statically references--> Logger Service
The issue is that both "services" are singletons, and both would need reference to each other as a constructor parameter. My first thought was property based injection, but I quickly found that seems to be a Temporal Coupling situation that is much undesired.
The main running idea now is, at the log level, have it call the service provider to create an email service (so it will get the singleton instance), but I was really trying to keep the class library also decoupled from the .Net Core injection system. Anyone have any recommendations in case I'm missing something?
Edit: After more thought, does it make sense perhaps to create an abstracted service provider of my own (a basic one) that can have another service injected into it? Then I could perhaps just pass that around instead in such cases.
Best Answer
I suggest you to read a great book about the
C#
dependency injection by Mark Seemann, with a lot of real world samples for different tasks you can do with it, even with circular dependencies similar to your case.In general, the main design rule is
You can't resolve the problem on its level
, and in this case it's true too. You really need a mediator here to resolve interactions between two loggers. It easily can save the state for both of them, and notify each other about changes.For example, you can introduce some
Target
for the messages, like this:So, in case of some trouble with one of your loggers, mediator send the message with corresponding type to notify other about issue.
Common approach for such cutting-edge logic is an
AOP
implementation (personally I prefer thePostSharp
, which provides you a general approach, even with conventional techniques to assign the aspects on your classes).As for decoupling your code from the
.Net Core
injection system, I suggest you to examine theLogger Factory
, which is:With
Logger Factory
you can even filter the messages to notify the all loggers about problems with other ones, connect to OS event logs and much more.