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:
GeneralMessage // both loggers got this
EmailMessage // only email logger got this
LoggerMessage // only logger got 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 the PostSharp
, 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 the Logger Factory
, which is:
The new framework creates an abstraction layer or wrapper that enables you to use whichever logging framework you want as a provider. This ensures you have the maximum flexibility in your work as a developer. Furthermore, even though it’s only available with .NET Core
, referencing .NET Core
NuGet packages like Microsoft.Extensions.Logging
for a standard Visual Studio .NET 4.6
project is no problem.
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.
.NET Framework
is a VM, a JIT compiler, an object memory system consisting of a memory allocator and a garbage collector, a loader, a linker, and a runtime system (collectively called the Common Language Runtime (CLR)) which executes and supports a language called Microsoft Intermediate Language (MSIL). It is also a class library called the Base Class Library (BCL) containing fundamental data structures (strings, arrays, linked lists, hash dictionaries, …) and abstractions thereof (lists, dictionaries, …) as well as other fundamental types (tasks, functions, abstractions for equality) and algorithms. It also comes with a wider range of libraries called the Framework Class Library (FCL) which has support for developing desktop applications (e.g. WinForms and WPF), data manipulation (LINQ) and lots of other things.
It is strictly a Windows-only, PC-only implementation. It is not Free Software or Open Source, although at least part of the source code is available under certain non-free non-open restrictive licenses; also a subset of the FCL is available as Reference Source under the MIT License.
It is largely monolithic, based on assemblies. The Framework must be installed at the target.
ASP.NET
is a web framework built on the .NET Framework, and thus is also strictly Windows-only; it is also deeply tied to Internet Information Server (IIS). It is also largely monolithic and based on assemblies. The Framework must be installed at the target.
.NET Core
is a VM, a JIT compiler, an object memory system consisting of a memory allocator and a garbage collector, a loader, a linker, and a runtime system (collectively called the CoreCLR) which executes and supports a language called Microsoft Intermediate Language (MSIL). It is also a class library called the Core Library containing fundamental data structures (strings, arrays, linked lists, hash dictionaries, …) and abstractions thereof (lists, dictionaries, …) as well as other fundamental types (tasks, functions, abstractions for equality) and algorithms. It also comes with a wider range of libraries called CoreFX which has support for developing desktop applications (UWP), data manipulation (LINQ) and lots of other things.
It is designed to be highly portable, and Microsoft itself develops, releases, maintains and supports fully equal ports (with fully equal support, fully equal functionality and simultaneous releases) for Windows, macOS, and Linux on AMD64, x86, and ARM.
It is highly modular, consisting of small NuGet packages that allow a "pay-as-you-go" style of development, paying (in the sense of memory, disk space, and maintenance) only for functionality that you actually use. The framework (or rather the parts of it that are used) is shipped with the app.
.NET Core is functionality-wise a subset of the .NET Framework, but not API-wise: even for functionality implemented in .NET Core, the API is not necessarily the same as the one in .NET Framework. This is most obvious in cases where .NET Framework is tightly tied to Windows and .NET Core instead has either an OS-independent alternative or multiple OS-native ones. Another obvious example is reflection, which is closely tied to the underlying runtime, which was completely rewritten for .NET Core.
So, a working .NET Core application does not automatically also work on .NET Framework, however since .NET Core is functionality-wise mostly a subset, there should be alternative APIs available that have the same functionality. The converse is not true: a working .NET Framework app can not necessarily be ported directly to .NET Core.
.NET Core is the future of .NET at Microsoft. It is going to replace all the different slightly incompatible independent implementations of .NET inside Microsoft.
ASP.NET Core
is a web framework for .NET Core, and thus is highly portable. It is also not tied to any specific web server. It is, in fact, not even tied to a specific .NET implementation, it also works on .NET Framework. It is functionality-wise a subset of ASP.NET, but not necessarily API-compatible.
It is highly modular, consisting of small NuGet packages that allow a "pay-as-you-go" style of development, paying (in the sense of memory, disk space, and maintenance) only for functionality that you actually use. The framework (or rather the parts of it that are used) is shipped with the app.
.NET Standard
is a common API specification for a common subset of APIs across .NET Framework, .NET Core, and Xamarin / Mono. Implementations supporting a specific version of .NET Standard can run all apps targeting that version (or a lower one), apps targeting a specific version of .NET Standard can run on all platforms implementing that version (or a higher one).
ISO CLI
There is also another (set of) standard(s) covering (parts of) the .NET ecosystem. Early on in the history of .NET, Microsoft submitted a set of standards to ECMA, and then on to ISO which cover a subset of .NET 2.0. These standards are called the *Common Language Infrastructure (CLI)*, and consist of the Common Intermediate Language (CIL) (a high-level bytecode language), the Virtual Execution System (VES) (an abstract machine for executing CIL), the Common Type System (CTS) and the Common Language Specification (CLS) (specifications covering types and APIs that both CLI implementations and language implementations on top of the CLI must provide, and restrictions they must obey in order for languages to be able to interoperate seamlessly), a language-independent specification of program Metadata (including e.g. debug data, again for language interop), and a Standard Library.
Best Answer
Use ViewComponent if you have some business logic to run. It supports Separation of Concerns (SoC) principle. You can inject parameters to ViewComponent class from view (use razor .cshtml file). ViewComponent views can be found in Views/Shared/Components. It can be strongly-typed. ViewComponent use asynchronous method calls, so users doesn't have to wait for all of the content of an entire page to load. Moreover, ViewComponent can be invoked as Tag Helper: you need to add your ViewCompenent as Tag Helper using @addTagHelpers directive. This feature gives developer editor support in the razor editor template.
Use Editor/Display Template when editing or displaying certain types or classes. For example, you want to specify that Product object must appear with specification table. It preserves DRY principle in your MVC application. It can be used as partial view that is model bound to the object it wants to display.