What bothers me about IoC and autowiring is the usability of IoC for objects that are created.
Lets say I have the a static Utils class, that is used across the system. When I decided to use IoC and DI, I easily changed Utils to be non-static and have all my components receive its instance.
However, auto-wiring works well only for components that are created during bootstrap, for objects that are created during run-time or as response of user operations, and that use Utils, auto-wiring doesn't work. Instead, I have to manually pass instance of Utils to every instance of every object that is created during runtime.
The only way around it that I can see is using the anti-pattern of passing the IoC container around, which I certainly wouldn't want to do.
Is there another way? Or am I forced to pass Utils manually around to every instance and class?
Note: This isn't a question of design. Sure, I could minimize the usage of this metaphorical Utils in various ways, but in many situations it is unavoidable.
The only way around it that I can see is using the anti-pattern of
passing the IoC container around, which I certainly wouldn't want to
do.
The answer is simply: use an abstract factory.
By defining the factory interface in the application and the factory implementation in the Composition Root (your bootstrapper code) you can prevent using the Service Locator anti-pattern. This factory implementation can hold a reference to the container and call it to request instances. Because that implementation is part of your bootstrapping logic, that implementation is a infrastructure component, and you are not using it as a service locator.
Example:
public interface IUnitOfWorkFactory
{
IUnitOfWork CreateNew();
}
Implementation in composition root:
internal class SimpleInjectorUnitOfWorkFactory
: IUnitOfWorkFactory
{
private readonly SimpleInjector.Container container;
public SimpleInjectorUnitOfWorkFactory(Container container)
{
this.container = container;
}
public IUnitOfWork CreateNew()
{
return this.container.GetInstance<IUnitOfWork>();
}
}
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.
Based on this question, THE way to initialize new object with runtime parameters when using ioc-container is to create Abstract Factory.
In my example, I have this class:
internal sealed class AssetsDownloadingProcess
{
private readonly IBackgroundWorker _backgroundWorker;
private readonly IAssetsStorage _assetsStorage;
private readonly Parameters _parameters;
public AssetsDownloadingProcess(IBackgroundWorker backgroundWorker,
IAssetsStorage assetsStorage, Parameters parameters)
{
_parameters = parameters.Clone();
_backgroundWorker = backgroundWorker;
_assetsStorage = assetsStorage;
}
}
And a factory to construct it:
internal sealed class AssetsDownloadingProcessFactory
{
private readonly IBackgroundWorker _backgroundWorker;
private readonly IAssetsStorage _assetsStorage;
public AssetsDownloadingProcessFactory(IBackgroundWorker backgroundWorker,
IAssetsStorage assetsStorage)
{
_backgroundWorker = backgroundWorker;
_assetsStorage = assetsStorage;
}
public AssetsDownloadingProcess CreateProcess(
AssetsDownloadingProcess.Parameters parameters)
{
return new AssetsDownloadingProcess(
_backgroundWorker, _assetsStorage, parameters);
}
}
as you can see, AssetsDownloadingProcess does not implement any interface and will never be replaced with another class. Therefore this factory is nothing more than useless piece of code. It could be completely omitted in favour of AssetsDownloadingProcessFactory constructor. However, then I can't use dependency injection to constructor.
I would like to use benefits of Injection from my IoC Container without the hassle of creating factory and creating useless code. What is the correct way to do this? Am I missing something or using DI wrong?
In general, you should prevent using runtime data to create and initialize your application components, as described here. The mere fact that runtime data is passed in through the constructor forces you to create a Factory.
The solution given by the article to the problem of injecting runtime data into components is to let runtime data flow through method calls on an initialized object graph by either:
pass runtime data through method calls of the API, or
retrieve runtime data from specific abstractions that allow resolving runtime data.
When runtime data is not used during object graph construction, the component can be created using DI inside the Composition Root and you problem therefore goes away.
Doing so however is not always feasible, and when it isn't, an Abstract Factory is the solution.
Since Object Composition should solely take place in the application's Composition Root however, this means that your Abstract Factory must be an Abstraction. Only this way can you prevent that the construction of your AssetsDownloadingProcess component takes place inside the Composition Root.
The way to do this is to:
Define an abstraction, i.e. IAssetsDownloadingProcessFactory in the application layer where the consumers of this factory live.
Create an implementation of this abstraction inside the Composition Root.
Not using an abstraction means that consumers will take a dependency on the concrete AssetsDownloadingProcessFactory class (which is a Dependency Inversion Principle violation) and it pulls the object composition out of the Composition Root. This will cause object composition to be scattered throughout the application, which hinders maintainability.
I'm having troubles getting the advantage of a IoC (DI) container like Ninject, Unity or whatever. I understand the concepts as follows:
DI: Injecting a dependency into the class that requires it (preferably via constructor injection). I totally see why the less tight coupling is a good thing.
public MyClass{
ISomeService svc;
public MyClass(ISomeService svc){
svc = svc;
}
public doSomething(){
svc.doSomething();
}
}
Service Locator: When a "container" is used directly inside the class that requires a dependancy, to resolve the dependancy. I do get the point that this generates another dependancy and I also see that basically nothing is getting injected.
public MyClass{
public MyClass(){}
public doSomething(){
ServiceLocator.resolve<ISomeService>().doSomething();
}
}
Now, what confuses me is the concept of a "DI container". To me, it looks exactly like a service locator which - as far as I read - should only be used in the entry point / startup method of an application to register and resolve the dependancies and inject them into the constructors of other classes - and not within a concrete class that needs the dependancy (probably for the same reason why Service locators are considered "bad")
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
public void main(){
DIContainer.register<ISomeService>(new SomeService());
// ...
var myclass = new MyClass(DIContainer.resolve<ISomeService>());
myclass.doSomething();
}
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
DI containers are supposed to help you create an object graph quickly. You just tell it which concrete implementations you want to use for which abstractions (the registration phase), and then it can create any objects you want want (resolve phase).
If you create the dependencies and pass them to the constructor (in the application initialization code), then you are actually doing Pure DI.
I would argue that Pure DI is a better approach in many cases. See my article here
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
I would say yes. You should create the object graph when your application starts up. This is called the composition root.
If you need to create objects after your application has started then you should use factories (mainly abstract factories). And such factories will be created with the other objects in the composition roots.
Your classes shouldn't do much in the constructor, this will make the cost of creating all the dependencies at the composition root low.
However, I would say that it is OK to create some types of objects using the new keyword in special cases. Like when the object is a simple Data Transfer Object (DTO)
I've recently been challenged on my view that singletons are only good for logging and configuration. And with Dependency Injection I am now not seeing a reason why you can't use your services or repositories as singletons.
There is no coupling because DI injects a singleton instance through an interface. The only reasonable argument is that your services might have shared state, but if you think about it, services should be stand alone units without any shared state. Yes they do get injected with the repositories but you only have one way that a repository instance is created and passed to the service. Since repositories should never have a shared state I don't see any reasons why it also cannot be a singleton.
So for example a simple service class would look like this:
public class GraphicService : IGraphicService
{
private IGraphicRepository _rep;
public GraphicService(IGraphicRepository rep)
{
_rep = rep;
}
public void CreateGraphic()
{
...
_rep.SaveGraphic(graphic):
}
}
No state is shared in service except repository which also doesn't change or have it's own state.
So the question is, if your services and repositories don't have any state and only passed in, through interface, configuration or anything else that's instantiated the same way they then why wouldn't you have them as singleton?
If you're using the Singleton pattern i.e a static property of a class, then you have the tightly coupling problem.
If you need just a single instance of a class and you're using a DI Container to control its lifetime, then it's not a problem as there are none of the drawbacks. The app doesn't know there is a singleton in place, only the DI Container knows about it.
Bottom line, a single instance of a class is a valid coding requirement, the only issue is how you implement it. The Di Container is the best approach. the Singleton pattern is for quick'n dirty apps where you don't care enough about maintainability and testing.
Some projects use singleton for dependence lookup before dependency injection gets populated. for example iBATIS jpetstore if I'm not mistaken. It's convenient that you can access your dependence gloablly like
public class GraphicService : IGraphicService
{
private IGraphicRepository _rep = GraphicRepository.getInstance();
public void CreateGraphic()
{
...
_rep.SaveGraphic(graphic):
}
}
But this harms testability (for not easy to replace dependence with test doubles) and introduces implicit strong dependence (IGraphicService depends on both the abstraction and the implementation).
Dependeny injection sovles these. I don't see why can't use singleton in your case, but it doesn't add much value when using DI.
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.