Can anyone provide an all-around, method injection example using Autofac?
I have checked the documentation, but I find it hard to understand how this works and how the method is resolved.
So, OK, it is pretty straightforward how to register everything, but how can I use it? For example, I'd like to have a method which gets an HttpContext injected. So, having something like this:
builder
.Register<MyObjectType>()
.OnActivating(e => {
var dep = new HttpContextWrapper(HttpContext.Current);
e.Instance.SetTheDependency(dep);
})
.InstancePerRequest();
Note: This is possible with constructor injection but I'd like to understand the method injection way.
Question is how to use the resolved instance? Is it possible using the method injection to get a result back by the method which receives the dependencies? The behavior is not anywhere near the parameter injection but somehow close to property injection?
Update
#fknx essentially answers my question, by saying:
Method injection simply means that your dependency is not passed as a
constructor parameter or directly assigned to a property, but that it
is set using a (setter) method instead
So, if I decide to use method injection, the method essentially is behaving like a setter (kinda like the Java setter methods), so it is possible to use this dependency throughout the class entity?
What is the reason to do that and how it benefits from property injection?
Here you can find a small example to get you started:
using System;
using Autofac;
public class Program
{
public static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>()
.OnActivating(e => e.Instance.SetMyDependency(new MyDependency()));
var container = builder.Build();
container.Resolve<MyService>();
}
}
public class MyService
{
private MyDependency _myDependency;
public void SetMyDependency(MyDependency myDependency)
{
_myDependency = myDependency;
Console.WriteLine("SetMyDependency called");
}
}
public class MyDependency
{
}
As stated in the documentation you can also call the method in the lambda expression which creates your service instance, if you are using Register instead of RegisterType.
but I find it hard to understand how this works and how the method is resolved.
This sounds a bit odd. Method injection simply means that your dependency is not passed as a constructor parameter or directly assigned to a property, but that it is set using a (setter) method instead.
I've created a .NET Fiddle so that you can check out the example.
Update
So, if I decide to use method injection, the method essentially is behaving like a setter (kinda like the Java setter methods)
Yes this is true.
so it is possible to use this dependency throughout the class entity?
This is also true, but this also holds for constructor injection if you store your dependency in a (readonly) field or property, and it is always the case for property injection.
What is the reason to do that and how it benefits from property injection?
To be honest I've never used method injection in C#. I would guess that it is more common in Java if you want to set a field through the corresponding setter method. In C# you can do the same with property injection.
Maybe I would use method injection if setting the dependency would involve rather complex code that I don't want to put into the property's setter or into the constructor.
However, in most cases I would advice you to use constructor injection whenever possible and property injection when it is not for whatever reason (e.g. circular dependencies).
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 am writing a console app in .Net core. I want to use dependency injection. My architecture is like this. Program contains a TradeProcessor (which does all the work) which in turn makes some CompoundTrades. I have got DI passing some classes into the TradeProcessor via its constructor and that whole ServiceProvider setup. That works fine.
Now, if i want to DI some classes into the CompoundTrade does the TradeProcessor have to pass them in via the constructor? I was under the impression that if you register the class to be constructed, all the classes you want to pass in, then they all got passed in "under the hood". You call CompoundTrade () but the other constructor gets called. Am i confusing that with DI in Asp.Net? What is the best design pattern for doing this? Stick all the ServiceProviders in a static class?
You call CompoundTrade() but the other constructor gets called.
That's not how dependency injection works. If you call a constructor explicitly, you get exactly that constructor.
You will need to reference you container and tell your container to create an instance of that class for you.
If you have an instance that needs to dynamically create new objects that are registered in the container, you will need to pass in the container and then use that to create those new objects. Don't call a constructor directly.
public TradeProcessor(IServiceProvider provider)
{
// save the provider in a field
}
public void ThisNeedsADynamicallyCreatedContainerObject()
{
if(condition)
{
var instance = this.provider.GetService<ICompoundTrade>();
}
else
{
var instance = this.provider.GetService<ISingleTrade>();
}
}
Disclaimer: actual syntax may vary depending on the dependency injection provider you use.
I am using .NET (MVC5, Web API etc). I understand constructor injection just about (fairly new to using it in anger).
I have a class with a method that has a dependency. I don't want to use constructor injection because then I will be creating the dependent object every time this class is instantiated (and most of the methods don't use this dependent object).
So I thought method injection sounded like it might be the thing. However I can't figure out how to do it (I am using Autofac).
So if my method is
void DoSomething(string x, int y)
and that method needs to use an implementation of IMyService, how do I do this without using the constructor injection?
The only method injection technique I have seen is one where effectively a method is called at instantiation. This doesn't seem to help my case, it still means that all instances create this dependency even if I am going to call a method that doesn't need it.
I'm sure it is something simple but I can't figure it out right now. Could you help me with an example please?
UPDATE
this is the crux of it. I like the idea of Lazy suggested by Jim and will try this. So is method injection as I suspected and if so I don't really understand the point of it - why use it instead of constructor injection?
public class MailService {
// lots of methods that don't need PlayerDataService
public void SendPlayersEmail() {
var service = new PlayerDataService();
var players = service.GetPlayers();
foreach(var player in players) {
SendEmail(player);
}
}
}
I don't want to use constructor injection because then I will be creating the dependent object every time this class is instantiated (and most of the methods don't use this dependent object).
There's the problem. Break that functionality out into a new class.
That is, at least in my experience, the best solution when a method does not fit into the rest of the class (or have dependencies that are not used anywhere else).
You should also consider that object allocation is pretty cheap, you need millions of allocations per second before the performance is hurt (unless you are using Ninject ;))
If the cost of instantiating your object during construction is an issue, you can wrap it in a Lazy<> to avoid unnecessary construction. This will cause your dependency to be constructed on the first call to the lazy's .Value.
I have a feeling this is just a misunderstanding on my part of DI in winforms.
I'm trying to implement Ninject into an existing winforms app. In Program.cs I am doing something similar to
IKernel kernel = new StandardKernel(new NinjectBindings());
Application.Run(kernel.Get<MainContainer>());
My NinjectBindings has
Bind<IFilterEngine>().To<FilterEngine>();
Then in a customer usercontrol (SearchResults.cs) in a form of the MainContainer form I am trying to use method injection like so
[Inject]
public void AddFilterEngine(IFilterEngine filterEngine)
{
_filterEngine = filterEngine;
}
The app compiles and runs fine however, my _filterEngine instance is null and the AddFilterEngine method is never called. Is this because SearchResults is not created with Ninject? It is hardcoded in its parent form. If so, I'm assuming every parent from this point needs to also be created with Ninject?
Injection only occurs when the instance is created through Ninject, i.e. by calling Kernel.Get<T>(), which is usually only done at the "topmost" point within your application or by Ninject creating this instance itself.
So unless you create your usercontrol by calling Kernel.Get<SearchResult>() (assuming the class is called SearchResult) using self-binding or by the container (as a constructor argument for example), your method will never get invoked, unfortunately.
You need to either use a field or a Property setter for Ninject to Inject your value on object creation.
[Inject]
public IFilterEngine FilterEngine { get; set; }
You can also pass it as a parameter to the constructor if you don't what this property to be public. This is the preferred method. Follow the examples on the Ninject website.
I'm still struggling a bit with OOP concepts and dependency injection so bear with me.
I have generated my Linq2Sql model with a User table and now I would like to be able to send a confirmation email to this user so I created a partial class file for my User object and I felt it was natural to add a SendConfirmationEmail() method to the User class. This method will use a MailService to send the actual email and I would like to use dependency injection to pass in the service so I created a constructor overload on the User object like this
public User(IMailService service) : this()
{
_service = service;
}
The SendConfirmationEmail method would look like this
public void SendConfirmationEmail()
{
_service.SendMail(params...);
}
I realize this is a kind of poor mans dependency injection and I hope to switch to a dependency injection framework later as I am getting more grips on this.
The problem for me is that I need to make a reference from my model dll to my service dll which does not seem right and because I am unsure of how nice my linq2sql generated entities plays with Dependency injection frameworks and OOP concepts (I think ninject looks most promising).
I was hoping someone with a bit more experience than me could tell I'm if I am going in the right direction with this. I know I can make it work but I would like to educate my self in doing it in the correct way in the same step.
I personally would change some things in your architecture:
I don't think that SendConfirmationEmail should be a method on your User object. But should be a method on another object with the user as a parameter. (this also better seperates your Dal from the other logic.
Second in this method use something like this:
Services.Get<IMailService>().SendMail(params ...);
You can implement Services as the folowin (just an example):
public class Services
{
protected static Dictionary<Type, object> services = new Dictionary<Type, object>();
private Services()
{
}
static Services()
{
// hard coded implementations...
services.Add(typeof(IMailService), new DefaultMailServiceImplementation());
}
public static T Get<T>() where T : class
{
Type requestedType = typeof(T);
return services[requestedType] as T;
}
}
By using a "Services"-class (or call it what you like) you add an additional layer between the IOC-framework and your code which makes it easy to change IOC-frameworks. Just change the implementation in the Get method to use one. You can also use a hardcoded temporary solution (until you use an IOC-framework) in the static constructor (like I did in the above example).
The problem with that approach is that much of the time the entity is going to come from the LINQ-to-SQL back-end, and so isn't going to use your constructor (LINQ-to-SQL creates objects in its own way; you cannot force LINQ-to-SQL to use your constructor) - so this would only be useful for the (few) objects you create yourself. Data-binding (etc) will also commonly use the parameterless constructor by default.
I wonder if this wouldn't work better as a utility method that accepts the service, or obtains the service itself via a factory / singleton.
I think you're ok doing this, but you might want to do two additional things to protect yourself from future cross-layer dependency problems:
Create an interface for your User
object. You should do this because
not doing so will mean that
everything that consumes this
business object will have to
reference the LINQ dlls
unnecessarily.
Move your dependency injection from
the constructor into a property.
You do this because constructor
injection tends to limit your
ability to dynamically create your
object. Doing this, though poses a
problem, since you would have to
implement a lot of null checking
code for _service. You can fix this
by creating an "empty"
implementation of IMailService and
make it the default value for
_service.