I'm using Ninject for DI in my ASP.NET MVC application. I'm resolving the ILog dependency in controllers using the below module
public override void Load()
{
var configPath = ConfigurationManager.AppSettings["Log4NetConfigPath"];
// Load the external config file for Log4Net
XmlConfigurator.Configure(new System.IO.FileInfo(configPath));
log4net.Util.LogLog.InternalDebugging = true;
Bind<ILog>().ToMethod((c) => LogManager.GetLogger("AVLogger")).InSingletonScope();
}
I'm calling the InSingletonScope() to provide a single instance of ILog instance throughout the application. I've some questions?
Do I need to really bother about having single instance of ILog? Can I remove the InSingletonScope method itself.
Does having a single instance of ILog create some performance issues?
It would depend on how expensive it is to create your logger. I don't know what log4net's performance characteristics are, but if it's not expensive you should just create a new one.
When you use InSingletonScope() that means the log will exist for as long as your worker process exists (ie when it's recycled or shut down, the logger will be destroyed). That also means the logger is hanging around when you don't need it. It's not so much of a "performance" issue, as it is one of managing resources.
Related
I am new to dependency injection pattern. I love the idea, but struggle to apply it to my case. I have a singleton object, let’s call it X, which I need often in many parts of my program, in many different classes, sometimes deep in the call stack. Usually I would implement this as a globally available singleton. How is this implemented within the DI pattern, specifically with .NET Core DI container? I understand I need to register X with the DI container as a singleton, but how then I get access to it? DI will instantiate classes with constructors which will take reference to X, that’s great – but I need X deep within the call hierarchy, within my own objects which .NET Core or DI container know nothing about, in objects that were created using new rather than instantiated by the DI container.
I guess my question is – how does global singleton pattern aligns/implemented by/replaced by/avoided with the DI pattern?
Well, "new is glue" (Link). That means if you have new'ed an instance, it is glued to your implementation. You cannot easily exchange it with a different implementation, for example a mock for testing. Like gluing together Lego bricks.
I you want to use proper dependency injection (using a container/framework or not) you need to structure your program in a way that you don't glue your components together, but instead inject them.
Every class is basically at hierarchy level 1 then. You need an instance of your logger? You inject it. You need an instance of a class that needs a logger? You inject it. You want to test your logging mechanism? Easy, you just inject something that conforms to your logger interface that logs into a list and the at the end of your test you can check your list and see if all the required logs are there. That is something you can automate (in contrast to using your normal logging mechanism and checking the logfiles by hand).
That means in the end, you don't really have a hierarchy, because every class you have just gets their dependencies injected and it will be the container/framework or your controlling code that determines what that means for the order of instantiation of objects.
As far as design patterns go, allow me an observation: even now, you don't need a singleton. Right now in your program, it would work if you had a plain global variable. But I guess you read that global variables are "bad". And design patterns are "good". And since you need a global variable and singleton delivers a global variable, why use the "bad", when you can use the "good" right? Well, the problem is, even with a singleton, the global variable is bad. It's a drawback of the pattern, a toad you have to swallow for the singleton logic to work. In your case, you don't need the singleton logic, but you like the taste of toads. So you created a singleton. Don't do that with design patterns. Read them very carefully and make sure you use them for the intended purpose, not because you like their side-effects or because it feels good to use a design pattern.
Just an idea and maybe I need your thought:
public static class DependencyResolver
{
public static Func<IServiceProvider> GetServiceProvider;
}
Then in Startup:
public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
DependencyResolver.GetServiceProvider = () => { return serviceProvider; };
}
And now in any deed class:
DependencyResolver.GetServiceProvider().GetService<IService>();
Here's a simplified example of how this would work without a singleton.
This example assumes that your project is built in the following way:
the entry point is main
main creates an instance of class GuiCreator, then calls the method createAndRunGUI()
everything else is handled by that method
So your simplified code looks like this:
// main
// ... (boilerplate)
container = new Container();
gui = new GuiCreator(container.getDatabase(), container.getLogger(), container.getOtherDependency());
gui.createAndRunGUI();
// ... (boilerplate)
// GuiCreator
public class GuiCreator {
private IDatabase db;
private ILogger log;
private IOtherDependency other;
public GuiCreator(IDatabase newdb, ILogger newlog, IOtherDependency newother) {
db = newdb;
log = newlog;
other = newother;
}
public void createAndRunGUI() {
// do stuff
}
}
The Container class is where you actually define which implementations will be used, while the GuiCreator contructor takes interfaces as arguments. Now let's say the implementation of ILogger you choose has itself a dependency, defined by an interface its contructor takes as argument. The Container knows this and resolves it accordingly by instantiating the Logger as new LoggerImplementation(getLoggerDependency());. This goes on for the entire dependency chain.
So in essence:
All classes keep instances of interfaces they depend upon as members.
These members are set in the respective constructor.
The entire dependency chain is thus resolved when the first object is instantiated. Note that there might/should be some lazy loading involved here.
The only places where the container's methods are accessed to create instances are in main and inside the container itself:
Any class used in main receives its dependencies from main's container instance.
Any class not used in main, but rather used only as a dependency, is instantiated by the container and receives its dependencies from within there.
Any class used neither in main nor indirectly as a dependency somewhere below the classes used in main will obviously never be instantiated.
Thus, no class actually needs a reference to the container. In fact, no class needs to know there even is a container in your project. All they know is which interfaces they personally need.
The Container can either be provided by some third party library/framework or you can code it yourself. Typically, it will use some configuration file to determine which implementations are actually supposed to be used for the various interfaces. Third party containers will usually perform some sort of code analysis supported by annotations to "autowire" implementations, so if you go with a ready-made tool, make sure you read up on how that part works because it will generally make your life easier down the road.
How to manage new tasks with PerRequestLifeTimeManager?
Should I create another container inside a new task?(I wouldn't like to change PerRequestLifeTimeManager to PerResolveLifetimeManager/HierarchicalLifetimeManager)
[HttpPost]
public ActionResult UploadFile(FileUploadViewModel viewModel)
{
var cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
Task.Factory.StartNew(() =>
{
// _fileService = DependencyResolver.Current.GetService<IFileService>();
_fileService.ProcessFile(viewModel.FileContent);
}, cancellationToken);
}
You should read this article about DI in multi-threaded applications. Although it is written for a different DI library, you'll find most of the information applicable to the concept of DI in general. To quote a few important parts:
Dependency injection forces you to wire all dependencies together in a
single place in the application: the Composition Root. This means that
there is a single place in the application that knows about how
services behave, whether they are thread-safe, and how they should be
wired. Without this centralization, this knowledge would be scattered
throughout the code base, making it very hard to change the behavior
of a service.
In a multi-threaded application, each thread should get its own object
graph. This means that you should typically call
[Resolve<T>()] once at the beginning of the thread’s
execution to get the root object for processing that thread (or
request). The container will build an object graph with all root
object’s dependencies. Some of those dependencies will be singletons;
shared between all threads. Other dependencies might be transient; a
new instance is created per dependency. Other dependencies might be
thread-specific, request-specific, or with some other lifestyle. The
application code itself is unaware of the way the dependencies are
registered and that’s the way it is supposed to be.
The advice of building a new object graph at the beginning of a
thread, also holds when manually starting a new (background) thread.
Although you can pass on data to other threads, you should not pass on
container-controlled dependencies to other threads. On each new
thread, you should ask the container again for the dependencies. When
you start passing dependencies from one thread to the other, those
parts of the code have to know whether it is safe to pass those
dependencies on. For instance, are those dependencies thread-safe?
This might be trivial to analyze in some situations, but prevents you
to change those dependencies with other implementations, since now you
have to remember that there is a place in your code where this is
happening and you need to know which dependencies are passed on. You
are decentralizing this knowledge again, making it harder to reason
about the correctness of your DI configuration and making it easier to
misconfigure the container in a way that causes concurrency problems.
So you should not spin of new threads from within your application code itself. And you should definitely not create a new container instance, since this can cause all sorts of performance problems; you should typically have just one container instance per application.
Instead, you should pull this infrastructure logic into your Composition Root, which allows your controller's code to be simplified. Your controller code should not be more than this:
[HttpPost]
public ActionResult UploadFile(FileUploadViewModel viewModel)
{
_fileService.ProcessFile(viewModel.FileContent);
}
On the other hand, you don't want to change the IFileService implementation, because it shouldn't its concern to do multi-threading. Instead we need some infrastructural logic that we can place in between the controller and the file service, without them having to know about this. They way to do this is by implementing a proxy class for the file service and place it in your Composition Root:
private sealed class AsyncFileServiceProxy : IFileService {
private readonly ILogger logger;
private readonly Func<IFileService> fileServiceFactory;
public AsyncFileServiceProxy(ILogger logger, Func<IFileService> fileServiceFactory)
{
this.logger = logger;
this.fileServiceFactory = fileServiceFactory;
}
void IFileService.ProcessFile(FileContent content) {
// Run on a new thread
Task.Factory.StartNew(() => {
this.BackgroundThreadProcessFile(content);
});
}
private void BackgroundThreadProcessFile(FileContent content) {
// Here we run on a different thread and the
// services should be requested on this thread.
var fileService = this.fileServiceFactory.Invoke();
try {
fileService.ProcessFile(content);
}
catch (Exception ex) {
// logging is important, since we run on a
// different thread.
this.logger.Log(ex);
}
}
}
This class is a small peace of infrastructural logic that allows processing files on a background thread. The only thing left is to configure the container to inject our AsyncFileServiceProxy instead of the real file service implementation. There are multiple ways to do this. Here's an example:
container.RegisterType<ILogger, YourLogger>();
container.RegisterType<RealFileService>();
container.RegisterType<Func<IFileService>>(() => container.Resolve<RealFileService>(),
new ContainerControlledLifetimeManager());
container.RegisterType<IFileService, AsyncFileServiceProxy>();
One part however is missing here from the equation, and this is how to deal with scoped lifestyles, such as the per-request lifestyle. Since you are running stuff on a background thread, there is no HTTPContext and this basically means that you need to start some 'scope' to simulate a request (since your background thread is basically its own new request). This is however where my knowledge about Unity stops. I'm very familiar with Simple Injector and with Simple Injector you would solve this using a hybrid lifestyle (that mixes a per-request lifestyle with a lifetime-scope lifestyle) and you explicitly wrap the call to BackgroundThreadProcessFile in such scope. I imagine the solution in Unity to be very close to this, but unfortunately I don't have enough knowledge of Unity to show you how. Hopefully somebody else can comment on this, or add an extra answer to explain how to do this in Unity.
Over time controllers develop a lot of dependencies, and creating an instance of controller becomes too expensive for each request (especially with DI). Is there any solution to make controllers singletons?
Creating instances of controllers is pretty fast and simple operation. What becomes too expensive is creating dependencies for each request. So, what you really need is many controllers which share same instances of dependencies.
E.g. you have following controller
public class SalesController : Controller
{
private IProductRepository productRepository;
private IOrderRepository orderRepository;
public SalesController(IProductRepository productRepository,
IOrderRepository orderRepository)
{
this.productRepository = productRepository;
this.orderRepository = orderRepository;
}
// ...
}
You should configure your dependency injection framework to use same instances of repositories for all application (keep in mind, you can have synchronization problems). Now creating dependencies is not expensive any more. All dependencies are instantiated only once, and reused for all requests.
If you have many dependencies and you are worrying about costs of getting reference to instance of each dependency and providing these references to controller instance (which I don't think will be very expensive), then you can group your dependencies (something like Introduce Parameter Object refactoring):
public class SalesController : Controller
{
private ISalesService salesService;
public SalesController(ISalesService salesService)
{
this.salesService = salesService;
}
// ...
}
public class SalesService : ISalesService
{
private IProductRepository productRepository;
private IOrderRepository orderRepository;
public SalesService(IProductRepository productRepository,
IOrderRepository orderRepository)
{
this.productRepository = productRepository;
this.orderRepository = orderRepository;
}
// ...
}
Now you have single dependency, which will be injected very quickly. If you will configure your dependency injection framework to use singleton SalesService, then all SalesControllers will reuse same instance of service. Creation of controllers and providing dependencies will be very fast.
So first an answer to the original question:
public void ConfigureServices(IServiceCollection services) {
// put other services bindings here
// bind all Controller classes as singletons
services.AddSingleton<HomeController, HomeController>();
// tell framework to obtain Controller instances from ServiceProvider.
services.AddMvc().AddControllersAsServices();
}
As stated in the original question, if controllers have big dependency trees consisting mainly of request Scoped or Transient dependencies then creating them separately for each request may have some footprint on scalability of your application (in Java for example Servlet instances are singletons by default exactly for this reason). While usually CPU and real time needed to create even a big dependency tree is negligible (unless you have some heavy computations or network communication in constructors of your components, which almost never is a good idea for transient or request scoped components), the memory usage footprint is something to reckon with. In case of common DB-Web apps memory is the main factor limiting number of concurrent requests that a single machine-node can handle. If every request has a separate copy of a big dependency tree, together they may consume a significant amount of memory (the other thing to watch for is initial stack size for a new thread, by the way).
The accepted answer 1220560 solves the problem as well, but I would consider it an ugly hack and it has some drawbacks: you need to create this artificial singleton service that will be used by your Controllers either as a service locator or a proxy for other services. If you have just one such singleton object for all your controllers then you are effectively hiding real dependencies of your Controller: for example if someone wants to write a unit-test for your Controller he needs to analyse carefully its implementation to see which dependencies it actually uses, so that he knows what mocks/fakes he needs to provide in his test setup. If later you change your Controller and as a result of your change the subset of services your controller uses changes as well, it is very easy to forget to update the test setup also. This may sometimes lead to bugs that are hard to track. Contrary to this, if your dependencies are declared explicitly as constructor params, you will get a compiler error in the test setup right away. Another thing you can do is to have a separate such a singleton proxy/service locator for each controller, but then it's a lot of hassle basically.
Regardless whether you use the solution proposed by me or the one from answer #1220560 you must be careful when injecting request Scoped dependencies into singleton objects as described in https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#registering-your-own-services right at the end of the "registering-your-own-services" section. You can find possible solutions to this problem here: how to use scoped dependency in a singleton in C# / ASP
Another thing to watch for is concurrency issue: singleton objects may be accessed concurrently by several threads handling different concurrent requests, so make sure to add proper synchronization to any non-thread-safe resources your singleton uses.
edit:
I've just realized the original question was about ASP.NET and this answer is for ASP.NET Core, so it probably won't work for "non-Core".
I believe I understand the basic concepts of DI / IoC containers having written a couple of applications using them and reading a lot of stack overflow answers as well as Mark Seeman's book. There are still some cases that I have trouble with, especially when it comes to integrating DI container to a large existing architecture where DI principle hasn't been really used (think big ball of mud).
I know the ideal scenario is to have a single composition root / object graph per operation but in a legacy system this might not be possible without major refactoring (only the new and some select refactored old parts of the code could have dependencies injected through constructor and the rest of the system using the container as a service locator to interact with the new parts). This effectively means that a stack trace deep within an operation might include several object graphs with calls being made back and forth between new subsystems (single object graph until exiting into an old segment) and traditional subsystems (service locator call at some point to code under DI container).
With the (potentially faulty, I might be overthinking this or be completely wrong in assuming this kind of hybrid architecture is a good idea) assumptions out of the way, here's the actual problem:
Let's say we have a thread pool executing scheduled jobs of various types defined in database (or any external place). Each separate type of scheduled job is implemented as a class inheriting a common base class. When the job is started, it gets fed the information about which targets it should write its log messages to and the configuration it should use. The configuration could probably be handled by just passing the values as method parameters to whatever class needs them but if the job implementation gets larger than say 10-20 classes, it doesn't seem very handy.
Logging is the larger problem. Subsystems the job calls probably also need to write things to the log and usually in examples this is done by just requesting instance of ILog in the constructor. But how does that work in this case when we don't know the details / implementation until runtime? Since:
Due to (non DI container controlled) legacy system segments in the call chain (-> there potentially being multiple separate object graphs), child container cannot be used to inject the custom logger for specific sub-scope
Manual property injection would basically require the complete call chain (including all legacy subsystems) to be updated
A simplified example to help better perceive the problem:
Class JobXImplementation : JobBase {
// through constructor injection
ILoggerFactory _loggerFactory;
JobXExtraLogic _jobXExtras;
public void Run(JobConfig configurationFromDatabase)
{
ILog log = _loggerFactory.Create(configurationFromDatabase.targets);
// if there were no legacy parts in the call chain, I would register log as instance to a child container and Resolve next part of the call chain and everyone requesting ILog would get the correct logging targets
// do stuff
_jobXExtras.DoStuff(configurationFromDatabase, log);
}
}
Class JobXExtraLogic {
public void DoStuff(JobConfig configurationFromDatabase, ILog log) {
// call to legacy sub-system
var old = new OldClass(log, configurationFromDatabase.SomeRandomSetting);
old.DoOldStuff();
}
}
Class OldClass {
public void DoOldStuff() {
// moar stuff
var old = new AnotherOldClass();
old.DoMoreOldStuff();
}
}
Class AnotherOldClass {
public void DoMoreOldStuff() {
// call to a new subsystem
var newSystemEntryPoint = DIContainerAsServiceLocator.Resolve<INewSubsystemEntryPoint>();
newSystemEntryPoint.DoNewStuff();
}
}
Class NewSubsystemEntryPoint : INewSubsystemEntryPoint {
public void DoNewStuff() {
// want to log something...
}
}
I'm sure you get the picture by this point.
Instantiating old classes through DI is a non-starter since many of them use (often multiple) constructors to inject values instead of dependencies and would have to be refactored one by one. The caller basically implicitly controls the lifetime of the object and this is assumed in the implementations (the way they handle internal object state).
What are my options? What other kinds of problems could you possibly see in a situation like this? Is trying to only use constructor injection in this kind of environment even feasible?
Great question. In general, I would say that an IoC container loses a lot of its effectiveness when only a portion of the code is DI-friendly.
Books like Working Effectively with Legacy Code and Dependency Injection in .NET both talk about ways to tease apart objects and classes to make DI viable in code bases like the one you described.
Getting the system under test would be my first priority. I'd pick a functional area to start with, one with few dependencies on other functional areas.
I don't see a problem with moving beyond constructor injection to setter injection where it makes sense, and it might offer you a stepping stone to constructor injection. Adding a property is usually less invasive than changing an object's constructor.
EDIT: I forgot to move the kernel into a non-generic parent class here and supply a virtual method to access it. I do realize that the example below, as is, would create a plethora of kernel instances.
I just learned how to do injection this past week and here's how I've got things set up currently:
using Ninject;
using System.Reflection;
namespace Infrastructure
{
public static class Inject<T>
{
static bool b = Bootstrap();
static IKernel kernel;
static bool Bootstrap()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return true;
}
public static T New() { return kernel.Get<T>(); }
}
}
And then I plan to make the various ninject module classes part of the Infrastructure namespace so that this will load them.
I haven't been able to find anything on here or Google that gives examples of how to actually organize the usage of Ninject in your project, but this seems right to me as it allows me to only need the Ninject reference in this assembly. Is this a more or less 'correct' way or is there a better design?
There are a few problems with how you are doing things now.
Let me first start with the obvious C# problem: Static class variables in generic classes are shared on a per T basis. In other words, Inject<IUserRepository> and Inject<IOrderRepository> will each get their own IKernel instance, which is unlikely what you really want, since it is most likely you need a single IKernel for the life time of your application. When you don't have a single IKernel for the application, there is no way to register types as singleton, since singleton is always scoped at the container level, not at the application level. So, you better rewrite the class as non-generic and move the generic type argument to the method:
Inject.New<T>()
The second problem is one concerned dependency injection. It seems to me you are trying to use the Service Locator anti-pattern, since you are probably explicitly calling Inject.New<T> from within your application. A DI container should only be referenced in the start-up path of the application and should be able to construct a complete object graph of related objects. This way you can ask the container to get a root level object for you (for instance a Controller in the context of MVC) and the rest of the application will be oblivious to the use of any DI technology. When you doing this, there is no need to abstract the use of the container away (as you did with your Inject class).
Not all application or UI technologies allow this BTW. I tend to hide my container (just as you are doing) when working with a Web Forms application, because it is impossible to do proper dependency injection on Page classes, IHttpHandler objects, and UserControl classes.