My WPF desktop application is attempting to use Ninject to inject some interface dependencies as follows. The app startup looks like this, (I think) auto-generated:
void App_Startup(object sender, StartupEventArgs e)
{
IKernel _Kernel = new StandardKernel();
_Kernel.Load(Assembly.GetExecutingAssembly());
}
I then have a NinjectModel-extending class whose Load method gets called by the above, and binding takes place like so:
Bind<Inheritance.IWindowProvider>().To<WindowProvider>().InSingletonScope();
My view models then take in an IWindowProvider and in this case I've also added the [Inject] attribute.
[Inject]
public LoginDetailsVM (IWindowProvider windowProvider) {
this.WindowProvider = windowProvider;
}
Elsewhere then (in another VM), I want to make an instance of this view model:
IKernel kernel = new StandardKernel();
LoginDetailsVM loginDetails = kernel.Get<LoginDetailsVM>();
However I get the "dreaded" error:
Error activating IWindowProvider
No matching bindings are available,
and the type is not self-bindable.
My initial search turns up that me instantiating StandardKernel twice is probably the issue, but I'm not sure how to access it otherwise.
Surely having to pass around an instance of the kernel somewhat defeats one of the points of having the injection?
Also, is the explicit Get<T>() form the accepted choice for obtaining instances, or is there a better implicit method of calling an injected constructor?
Apologies for what might seem a naive understanding here, I'm totally new to Ninject and DI generally.
The problem isn't passing around the kernel - it's where you're accessing it. If you're referencing it outside of your composition root (App_Startup) then creating a new one isn't any better than passing around the one you already created.
When you need to resolve something outside of your composition root and you don't want to reference the container, one solution is to create a factory. Your component that needs to resolve something doesn't ask the container for it - it asks the factory for it.
The factory, in turn, is set up to resolve it from the container. But that's set up in your composition root, and the factory could be replaced with an implementation that doesn't involve the container. So you can still say that your component doesn't depend on or talk to the container.
Here's some documentation on configuring Ninject to supply an instance to a factory.
Think of an IOC container like a magic dictionary with type and object instances stored in it.
If you did
Void a method (){
Var dictionary = new dictionary ();
dictionary.Add(typeof(IFOO), new Foo());
}
Void other_method(){
Var dictionary = new dictionary ();
IFOO instance =Dictionary[typeof(IFOO)];
// would you expect this to work?
}
Often the singleton pattern is used to provide access to an IOC container.
Related
I am trying to understand Dependency Injection where usually everything is injected as either via Constructor or Property Injection.
So far I have understood that it basically revolves around interface to mock the class.
I am checking out Nop Commerce where I came across CustomerModelFactory which accepts couple of Domain class like CustomerSettings,DatetimeSettings etc..
Now when I check the DependencyRegistrar.cs class, I don't see how the dependency registration or even in the same class, I don't see the new instance of CustomerSettings created anywhere.
So my question is when we inject concrete class in constructor of class, where do we register it or how IOC container supply the instance?
CustomerModelFactory.cs
public partial class CustomerModelFactory : ICustomerModelFactory
{
// all below are concrete class
public CustomerModelFactory(AddressSettings addressSettings,
CaptchaSettings captchaSettings,
CatalogSettings catalogSettings,
CommonSettings commonSettings,
CustomerSettings customerSettings,
DateTimeSettings dateTimeSettings,
}
DependencyRegistrar.cs
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
builder.RegisterType<CustomerModelFactory>().As<ICustomerModelFactory>().InstancePerLifetimeScope();
}
}
I couldn't find where below is done:
CustomerSettings settings = new CustomerSettings();
or
CatalogSettings settings = new CatalogSettings();
How can I understand how this is working?
That's why DI does not really reduce complexity, instead, it hides complexity under surface and offload lifecycle management to another thing that you don't really know too much, as each DI framework is different. Anyway, that is another topic.
Here is to answer your question, ignore which DI framework, just think in general, there are 3 ways for you to get an instance of an object
Create the instance directly when you need it
CustomerSettings settings = new CustomerSettings();
Create the instance by Reflection when you need it
Type t = typeof(CustomerSettings);
CustomerSettings settings = Activator.CreateInstance(t) as CustomerSettings;
Cache all instances in a dictionary and look up when using the type name
something can be like this:
Dictionary<Type, object> lookup;
lookup.Add(typeof(CustomerSettings), new CustomerSettings()):
(This way does not generate a new instance though).
Now if you need the instance, you ask the dictionary to give it to you
lookup[typeof(CustomerSettings)]
This action, is called Resolved in many DI framework.
How does the DI framework find it though?
To do this, many DI framework will use reflection to find the matching type. There should always a process to register the types you want DI framework to resolve automatically. It means, you tell DI framework what type it needs to be aware, and then give it back to me when you look up using the type.
For example, you may see code like this:
container.Register<CustomerSettings>();
In this case, CustomerSettings is a class type, so DI knows how to create it when you need it.
However, if you are registering an interface
container.Register<ICustomerSettings, CustomerSettings>():
The above is one syntax to register interface and its concrete type. Basically, you tell DI, this is the type, and that is the implementation. So when you do this:
var setting = container.Resolve<ICustomerSettings>();
You will get an instance of CustomerSettings.
It will work if you have multiple implementations of the same interface, but you need some special handling. Different DI handles it differently.
Hopefully so far it makes a little sense.
Each DI framework has an IOC container, which acts like a dictionary. You register the type into there, and ask it to give it back.
There are more details, but I will not cover in here.
Concrete types are not automatically resolved by MS.DI; they need to be registered explicitly. NopCommerce, therefore, registers them inside its DependencyRegistrar class (on line 241):
//register all settings
var settings = typeFinder.FindClassesOfType(typeof(ISettings), false).ToList();
foreach (var setting in settings)
{
services.AddScoped(setting, serviceProvider =>
{
var storeId = DataSettingsManager.IsDatabaseInstalled()
? serviceProvider.GetRequiredService<IStoreContext>()
.GetCurrentStoreAsync().Result?.Id ?? 0
: 0;
return serviceProvider.GetRequiredService<ISettingService>()
.LoadSettingAsync(setting, storeId).Result;
});
}
I'm converting my code to use an IoC Container with StructureMap. Trying to get my head around things, and I feel it's starting to 'click' and I can see how it makes so much sense with the back-end side.
However, I'm working my way down I've spotted a few sitautions where I'm not sure how to make it work. Specifically, the case where my original constructor did something important with an argument that isn't really a dependency, or something that will change at run-time.
Let's say I start with this (pre IoC Container), where I was passing my dependencies using a constructor, but also sending it an ImportantObject that's run-time dependent:
IMyPageViewModel myPageViewModel = new MyPageViewModel(importantObject, dialogManager, pageDisplay, viewModelProvider)
and here it is doing its constructing:
public MyPageViewModel(ImportantObject importantObject, IDialogManager dialogManager,IPageDisplay pageDisplay, IViewModelProvider viewModelProvider)
{
this.dialogManager = dialogManager;
this.pageDisplay = pageDisplay;
this.viewModelProvider = viewModelProvider;
importantObject.DoThatImportantThing();
}
Now, I'm migrating to use the IoC container, and at first I think I should do something like this:
//I need to create an instance to use, so I use my IoC container:
IMyPageViewModel myPageViewModel = container.GetInstance<IMyPageViewModel>();
then letting it resolve it's dependencies, however importantObject is something that's set at runtime. I can't register it as a dependency:
public MyPageViewModel(IDialogManager dialogManager,IPageDisplay pageDisplay, IViewModelProvider viewModelProvider, IContainer container)
{
this.dialogManager = dialogManager;
this.pageDisplay = pageDisplay;
this.viewModelProvider = viewModelProvider;
//however, here I have no access to the important object that I previously passed in my constructor
importantObject.DoThatImportantThing(); //obviously error
}
I thought maybe I should be creating using 'new', and passing the IoC container:
IMyPageViewModel myPageViewModel = new MyPageViewModel(importantObject, container)
then letting it resolve it's dependencies in the constructor:
public MyPageViewModel(ImportantObject importantObject, IContainer container)
{
this.dialogManager = container.GetInstance<IDialogManager>();
this.pageDisplay = container.GetInstance<IPageDisplay>();
this.viewModelProvider = container.GetInstance<IViewModelProvider>();
importantObject.DoThatImportantThing();
}
But that strikes me as not a good idea, specifically, I can't run it with a test register and have it create a dummy/stub "MyPageViewModel" for unit testing.
The only other thing I can think of is to remove all the logic from the constructor and putting it in an initialize method, or property setters. However, this means I have to ensure that initialize is always called before use and it will hide errors/problems.
Are any of these options sensible, how should I manage passing a run-time dependent object in a constructor with Dependency Injection?
I tried to stray away from static factories, as I've read lots about them being anti-pattern/bad practice.
Edit: In response to Bruno Garcia's answer I decided to use a factory type pattern that holds the container and deals with object creation like this:
class PageProvider : IPageProvider
{
public MyPageViewModel GetMyPage(ImportantObject importantObject)
{
//might just get, if it's a single only instance
return MyPageViewModel(ImportantObject importantObject,
container.GetInstance<IDialogManager>(),
container.GetInstance<IPageDisplay>(),
container.GetInstance<IViewModelProvider>())
}
}
StructureMap supports passing arguments to Resolve. This could help you with passing the ImportantObject to the Service you are resolving.
It's worth noting that if you pass your container around, things can get really messy really fast. Avoid using it as a Service Locator.
Ideally you'd use the container to resolve an entry point (e.g: Controller, Consumer worker) and from that point on, there's no direct use of the container anymore. If you need to control the lifetime of the dependencies you are taking into your constructor, there are a number of ways to go about that like:
Taking a Factory or a Func<>.
I suggest you reading carefully the docs of the Container you want to use to understand who controls the lifetime of objects (if a Component implements IDisposable, who's going to dispose it?). When are lifetime scopes created/disposed?
IoC Container's are great but it's very easy to find yourself troubleshooting memory leaks if you don't carefully understand the concept of lifetime ownership.
I think I'm missing a key part of how to actually use IoC/DI. I happen to be using the Unity container. I know how to setup a class to have it's dependencies injected and I also know how to make Unity register a type.
But what I don't know is how to actually then make use of these registrations.
So for example:
var container = new UnityContainer();
container.RegisterType<IRepository, XmlRepository>();
var service = new MyService(container.Resolve<IRepository>());
public interface IRepository
{
void GetStuff();
}
public class XmlRepository : IRepository
{
public void GetStuff()
{
throw new NotImplementedException();
}
}
public class MyService
{
private readonly IRepository _myRepository;
public MyService(IRepository repository)
{
_myRepository = repository;
}
}
Here I have a service layer which accepts a parameter of type IRepository. It's the container part that I seem to not be understanding.
Isn't the point of IoC/DI to be able to not have to manually resolve types every time I need to create an instance? In my code I'm getting the container to resolve a type, unless I'm misunderstanding how this is supposed to work, isn't the container supposed to somehow automatically (with reflection?) inject the dependency I told it to use when I registered the type? var service = new MyService(...) Is calling container.Resolve the correct way of doing this?
I've created a container, but how do I share this container amongst my project/code? This sort of relates to the first question. I had previously thought that there was a single place that you register types. So far the only way I can see how to get around this is to:
Keep registering types wherever I use them and end up with duplicated code
Pass the container around to every place I'm going to be resolving types
Neither of these ways are how I'd expect this to work
Isn't the point of IoC/DI to be able to not have to manually resolve types every time I need to create an instance?
No, that's the point of a DI Container, but there are drawbacks to using a container as well. Favour Pure DI over using a DI Container, as this will teach you how to use Dependency Injection using only first principles.
I've created a container, but how do I share this container amongst my project/code?
You don't. The DI Container should only be used in the Composition Root (if you use a DI Container at all).
Put your container setup in a module that runs when your program starts. You can call it from Main, for example. This is called a boot strapper.
See Dependency Injection with Unity for a good example of how to do this.
You don't need to do new MyService(container.Resolve<IRepository>()). To get an instance of MyService, just use container.Resolve<MyService>(); it will automatically resolves the dependencies for MyService.
I have some services in my asp.net mvc application that listen for AMQP messages and invoke methods.
No controllers depend on this, so it won't get instantiated on its own.
I could instantiate it manually, explicitly providing its dependencies with kernel.Get but it feels like I shouldn't have to do that.
Can I make Ninject instantiate classes in singleton scope eagerly even when nothing else depends on it?
You cannot have ninject instantiate stuff in case you don't ask it to instantiate something yourself.
The simple way is to ask ninject to instantiate things at composition root:
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies()); // loads all modules in assemlby
//...
// resolution root completely configured
kernel.Resolve<IFooSingleton>();
kernel.Resolve<IBarSIngleton>();
There is one alternative, actually, which is not the same, but can be used to achieve a similar effect. It requires that there is at least one single other service instantiated soon enough: Ninject.Extensions.DependencyCreation.
It works like this:
kernel.Bind<string>().ToConstant("hello");
kernel.Bind<ISingletonDependency>().To<SingletonDependency>()
.InSingletonScope();
kernel.DefineDependency<string, ISingletonDependency>();
kernel.Get<string>();
// when asking for a string for the first time
// ISingletonDependency will be instantiated.
// of course you can use any other type instead of string
Why
Ninject is unlike some other containers (for example Autofac) not "built" in stages. There's no concept of first creating the bindings, and then creating the kernel to use them. The following is perfectly legal:
kernel.Bind<IFoo>()...
kernel.Get<IFoo>()...
kernel.Bind<IBar>()...
kernel.Get<IBar>()...
so ninject can't possibly know when you want the singletons to be instantiated. With autofac it's clear and easy:
var containerBuilder = new ContainerBuilder();
containerBuilder
.RegisterType<Foo>()
.AutoActivate();
var container = containerBuilder.Build(); // now
Coming from Guice in Java, I've sorely missed the pattern of eager singletons. They are useful in scenarios where for example modules act as plugins. If you imagine that a service is assembled from modules that are specified in a configuration, you could see a problem of then also trying to specify what this module needs to be auto-instantiated when the application is started.
For me the module is where the composition of the application is defined and separating eager singletons into another place in the code feels more clunky and less intuitive.
Anyway, I've been able to very easily implement this as a layer on top of Ninject, here's the code:
public static class EagerSingleton
{
public static IBindingNamedWithOrOnSyntax<T> AsEagerSingleton<T>(this IBindingInSyntax<T> binding)
{
var r = binding.InSingletonScope();
binding.Kernel.Bind<IEagerSingleton>().To<EagerSingleton<T>>().InSingletonScope();
return r;
}
}
public interface IEagerSingleton { }
public class EagerSingleton<TComponent> : IEagerSingleton
{
public EagerSingleton(TComponent component)
{
// do nothing. DI created the component for this constructor.
}
}
public class EagerSingletonSvc
{
public EagerSingletonSvc(IEagerSingleton[] singletons)
{
// do nothing. DI created all the singletons for this constructor.
}
}
After you've created your kernel, add a single line:
kernel.Get<EagerSingletonSvc>(); // activate all eager singletons
You use it in a module like this:
Bind<UnhandledExceptionHandlerSvc>().ToSelf().AsEagerSingleton();
I am in need of adding an item of type IVehicle which is injected at runtime from constructor to a for loop.
IVehicle vehicle;
for (int i=0;i<=someValue;i++)
{
list.insert(i,vehicle);
//some processing to assign values
}
now because Ivehicle is already injected by this time, my list has same value despite the value on view different and coming through the controller. How can I new up this object everytime
EDIT
The best way to new up this object everytime I found was to request new from the kernel that was injecting it. I am using Ninject as said earlier.
All I did was use a create a variable of type IKernel and got the constructor to inject it and then I used kernel.Get() to get a new instance. Dont know if this is the best way to go about doing this as my constructor is really greedy. :)
private IKernel _kernel;
get this injected in constructor, no need to do any bindings as Ninject already knows this.
then you can use the _kernel to get new, by using _kernel.Get<>().
Hope this helps someone..
The best way for this scenario is to inject Func<IVehicle>. And add the binding below. That way you have no reference to Ninject in you production code. Furthermore this kind of factory methods are planned to be added to the next release of Ninject. The binding below will not be necessary anymore.
Bind<Func<IConfigurationView>>().ToMethod(ctx => (() => ctx.Kernel.Get<IConfigurationView>()));