I'm using NInject on a new web application and there are two things that are unclear to me:
Don't I need to keep a reference to the Kernel around (Session/App variable) to insure that GC doesn't collect all my instances? For example, if I specify .Using() and then the Kernel object gets collected, aren't all my "singletons" collected as well?
If I do need keep a reference to a Kernel object around, how do I allow the arguments passed in to WithArguments() to change or is that not possible.
It's true that you don't want to pass around the kernel. Typically, in a web app, I store the kernel in a static property in the HttpApplication. If you need a reference to the kernel, you can just expose a dependency (via constructor argument or property) that is of the type IKernel, and Ninject will give you a reference to the kernel that activated the type.
If you use WithArguments() on a binding, they will be used for all activations. If you use IParameters, they will only be used for that activation. (However, if the service you're activating has a re-usable behavior like Singleton, it won't be re-activated even if you pass different IParameters.)
This is a common pitfall when starting to use a IoC container. See this related question.
In a nutshell:
It's bad practice to pass your container around (been there, done that, and it really hurts)
If you really need to invocate directly the container, first consider abstracting to an injected factory, then as a last resource consider using a static gateway to the container
Mark Seeman -- author of Manning Dependency Injection Suggust to Use Hollywood principle Don't call us(IOC framework) instead We will call you ... .. The IOC container should be placed in the Application's Composition root.. and it needs to instantiated as requested.. like wat nate mentioned
.. For the Web Application the Composition root is Global.asax file where the u can use the override the startup events and There u can bind your Ninject to resolve the component
Related
I have a WebApi that needs to add a singleton for DI during Setup. But I need to instantiate it during Startup. All of the example code I've found online shows something like this:
services.AddSingleton(new MyService());
This is great, but what do you do if MyService() takes arguments that are setup in DI? For instance, if my service's constructor is like this:
public MyService(ILogger<MyService> logger, IConfiguration config)
There must be a way to instantiate the object when adding it to the DI services, but I'm at a loss.
I'm using .NET 6.
Thanks
You basically have two options:
Create the object -with its dependencies- before or during the registration process. With ASP.NET Core the typical place to do this is inside the Startup.ConfigureServices method (or before).
Register it normally and resolve it directly after the container was constructed. In ASP.NET Core this typically means inside the Configure method.
In case the object needs to be available before registration (for instance because the registrations depend on the outcome of a method call on that object), it's important to keep that object as slim and with as little dependencies as possible. Such object, for instance, might have more functionality and dependencies than needs to execute at that moment. In that case it's good to split the object into smaller pieces, such that you only have to compose the least amount of dependencies to get the logic executed.
For instance, instead of injecting an IConfiguration, think about injecting just the parts of the configuration that the object requires. Also think about whether you require logging at this point. Especially logging is tricky, because it's tightly coupled into the DI infrastructure, which makes it more difficult to construct such class manually. This could hold for other framework dependencies as well, because most framework dependencies are registered in the built-in configuration system.
For application components, on the other hand, it should typically fairly easy to compose them before hand. You would usually see that the kinds of services you need this early in the process tend to have little dependencies -or- they can be refactored as such.
If that 'startup' service requires a deeper object graph resolving it from the DI container makes the most sense, but again, that requires the DI Container to be built. Only when executing the Configure method (or later) do you have access to the container.
What I would suggest is the have the following call in the startup:
builder.Services.AddSingleton<IMyService, MyService>(); Then the DI will instantiate any objects that are required in the MyService constructor.
Hope this helps.
Is there a way to instantiate a class without a constructor if I don't have a handle to the container?
If I call container.RegisterType<IMyClass , MyClass>() I know I can use unity to instantiate an object in a constructor.
Someclass(IMyClass myClass)
var s = new Someclass();
I also know I can use
container.Resolve<IMyClass>() outside a constructor if I have a handle to the container, or use the DependencyFactory, which is also the same thing.
If I am writing code for a large project that doesn't save a handle to the container, and it is not appropriate to use a constructor, is there a way to instatiate class using unity?
you should not be referencing the container in your classes. You container should be orchestrating the construction of the object graph and your class should not be calling it, it should be calling your classes.
Ideally your container should not be used outside of the Composition Root. See this answer
The point I (and Belogix) was trying to make (not very well it seems) is that you should never need to create dependent objects directly if you are using DI correctly. Passing the container around is a code smell and you should avoid this if at all possible (which it almost always is). If you require an instance of a class in a place where you 'don't have a handle to the container' you should be asking for an instance of that class through your object's constructor. Doing this allows the IoC container to know that your object has a dependency and it can then supply an instance of that dependency when the container creates an instance of the class. If you follow this principal with every dependency all the way up your chain then your composition root becomes the only place that you need to create your objects, and you can do it manually (poor man's DI), or you can configure a container to do it for you.
I suggest you read this post it really helped me understand the concept of a composition root and why not leaking your container throughout the application is a Good Idea.
If you want to create an object without calling the constructor and without a handle to the container then you can use GetUnitializedObject as outlied in this answer but you have to ask yourself, if you are swimming that hard upstream to create your objects, surely there must be a better way?
I was only trying to point out what I consider the currently accepted best practices around using a container.
While reading about IoC/DI containers, I read in a few places (e.g. here and here and here) that the container should ideally be used only at startup.
Does this mean you need to always rely on the container injecting the parameters to the constructors of the objects you need to resolve? Even then, do you not still need the container to create those types?
What about classes that use an instance of a central service (typically a singleton) which is registered in the container?
What about classes whose constructors require parameters of types that are not registered in the container?
While reading about IoC/DI containers, I read in a few places (e.g.
here and here and here) that the container should ideally be used only
at startup.
They mean that you configure the container and register all components at application startup (or otherwise very early).
It makes sense, because typically you have a one or a few root objects (e.g. instantiated first by the container) and from there on the container should take of resolving dependencies if all of them are configured correctly.
In other situations you have to request the root objects from the container (e.g. a console or Windows Service application) because there's no way for it to integrate with the platform at startup like it can do for example for ASP.NET WebApi or MVC (well, no way excepting assembly instrumentation).
More exactly, you need to call Resolve or GetInstance (or whatever the DI framework supports) for the root objects in these situations.
What about classes that use an instance of a central service
(typically a singleton) which is registered in the container?
All DI containers support per-container lifetime, which is what a singleton basically gives you. So, you can register a singleton instance in the container with a lifetime matching that of the container and then inject that instance where you need it.
EDIT: as it turns out I got this backwards. You have here the options of either registering these classes with the container and let it do the injection, or call Resolve manually. However, as I said in the comments, some people consider service locator to be an anti-pattern. I think that if you don't abuse it and use it when it's more trouble than worth to register with the container, then do it.
What about classes whose constructors require parameters of types that
are not registered in the container?
I think that's the point of DI. If you want a component to not use DI, then don't register it and instantiate it as usual, via new.
Otherwise, if unresolved dependencies are detected by the DI container then it will most likely throw. And it should throw so you can see the error and correct it.
It could seem a stupid question because in my code everything is working, but I've registered a singleton this way with my Unity container _ambientContainer:
_ambientContainer.RegisterType<Application.StateContext>(new ContainerControlledLifetimeManager());
In order to avoid to use my local field, I use:
get {
return ServiceLocator.Current.GetInstance<Application.StateContext>();
}
inside my get property to get an instance of my object.
This way I get always the same instance (Application.StateContext is still a singleton) or does GetInstance create a new one?
Is it better to use the local _ambientContainer field instead?
get {
return _ambientContainer.Resolve<Application.StateContext>();
}
Thank you.
Passing around instances of the container to consumer classes isn't generally a good idea, since you are no longer guaranteed to have a single place in your application where components and services are being registered (known as the Composition Root).
Classes should state their dependencies in their public API, ideally by specifying them as constructor arguments, which the container will automatically provide an instance for whenever it's been asked to resolve a specific type (a process known as Autowiring).
Dependency Injection is usually the preferred choice but it isn't always applicable. In those cases using a Service Locator, like you're doing in your example, is the next best solution to decouple a class from its dependencies.
In conclusion, if Dependency Injection is not an option, I would avoid having my classes reference the container directly and instead have them access it through a Service Locator.
Preferably you should avoid both ways of (ab)using your container.
The ServiceLocator is considered an anti-pattern in modern application architecture.
I'm assuming that the ServiceLocator type is from the CommonServiceLocator project, and that you're using the Unity adapter, in which case GetInstance invokes container.Resolve, so both lines are equivalent.
You can view the source here - http://commonservicelocator.codeplex.com/wikipage?title=Unity%20Adapter&referringTitle=Home
More specifically, What's the best approach for classes where state matters, within an application which implements Dependency Injection.
Say I need access to an object that's in a particular state. For example, this object might have been initiated in a different thread, or by a process I have no control over.
A good example of an object like this that already exists in .NET is the HttpContext.
In this case, Microsoft decided to go with the Static approach, so I just say:
var currentObj = HttpContext.Current;
And this gives me a particular instance of an object without having to worry where it came from.
The problem with the Static approach is that it doesn't play very nicely with dependency injection.
The other option is to configure your certain class as a Singleton in your IoC Container. This means that you can inject it, and depending on the current IoC Container config it'll be the correct instance of the class.
However, the downfall of this approach is that the stateful importance of the object is no longer explicit in the code, it's not obvious by looking at it. With the Static class used to access and instance it's more clear that the state is important. Maybe that doesn't matter though.
So, is there a pattern that helps me out here?
Context:
For context, I'm working on an application which has many instances of a class performing IO operations. They exists within their own threads.
I want to be able to interact with those objects (background tasks) via a web interface, so a Controller. I want to be able to interrogate them, and manipulate them etc.
Update:
Sorry, I think my use of the term "stateful" is a bit misleading. let me explain some thing:
"state" is probably the wrong word. I mean communicating with an object whereby I don't have control over it's lifecycle.
It is funny that I use "stateful" when talking about static classes. That's why I gave the HttpContext example, as that exactly what it does. The Current property gets you a very specific instance, not any new instance.
When I say that static doesn't play nice with DI, I meant, you can't inject Static classes. I could create a wrapper, yes, but I'm just pushing the problem elsewhere no?
I should have been more clear about my definition of Singleton. I meant a Singleton lifestyle, as defined in an IoC Container.
I always prefer Singleton over static. In fact, I almost never use statics in my own classes.
True singletons and static classes are both very difficult to write automated tests against. Do you mean a single instance looked up at runtime? That would make sense to me but I don't know the right construct to use in C#. The analog in Java is JNDI.
Neither or both. Presuming the stateful dependency is thread-safe the better approach is to build at least a basic layer of abstraction around said dependency then inject said abstraction into your classes. Singleton vs static becomes pretty immaterial then.