A proper DI implementation?
-
I'm fairly new to dependency injection but it seems like a proper DI implementation will be fairly complex. For example, DI requires a centralized class that manages the configuration and resolves the dependencies at runtime. DI is also based on the concept of using interfaces. For example, a SpecialLogger should use an ILogger interface. The centralized DI manager class will need to register types - for example, associate ILogger to SpecialLogger. SpecialLogger will also need to implement the ILogger interface so SpecialLogger can be used through the DI ILogger interface. Therefore, it seems like a sln using DI will need multiple projects to support DI. Here is an example for logging: * MyCompany.MyDivision.Framework.DI.Management - this would have the DI manager where dependency types are registered and resolved at runtime * MyCompany.MyDivision.Framework.Logging - this would have the implementation of a logging class. The main logging class would need to implement ILogger. * MyCompany.MyDivision.Framework.DI.Interfaces - this would have the ILogger interface. Interfaces would need to be stored in a separate class library from the DI manager because both the DI manager and SpecialLogger use the ILogger interface. Since the DI manager associates SpecialLogger to ILogger a circular reference would be encountered without a separate class library to store the ILogger interface. Does this sound like a reasonable assessment? Like I said I am just learning DI so if you can share any real-world experience with a DI implementation that would be appreciated.
-
I'm fairly new to dependency injection but it seems like a proper DI implementation will be fairly complex. For example, DI requires a centralized class that manages the configuration and resolves the dependencies at runtime. DI is also based on the concept of using interfaces. For example, a SpecialLogger should use an ILogger interface. The centralized DI manager class will need to register types - for example, associate ILogger to SpecialLogger. SpecialLogger will also need to implement the ILogger interface so SpecialLogger can be used through the DI ILogger interface. Therefore, it seems like a sln using DI will need multiple projects to support DI. Here is an example for logging: * MyCompany.MyDivision.Framework.DI.Management - this would have the DI manager where dependency types are registered and resolved at runtime * MyCompany.MyDivision.Framework.Logging - this would have the implementation of a logging class. The main logging class would need to implement ILogger. * MyCompany.MyDivision.Framework.DI.Interfaces - this would have the ILogger interface. Interfaces would need to be stored in a separate class library from the DI manager because both the DI manager and SpecialLogger use the ILogger interface. Since the DI manager associates SpecialLogger to ILogger a circular reference would be encountered without a separate class library to store the ILogger interface. Does this sound like a reasonable assessment? Like I said I am just learning DI so if you can share any real-world experience with a DI implementation that would be appreciated.
The DI framework is usually a component of the application layer (in my experience) e.g If you had an ASP.NET MVC App and you were using structure map, its your front end application that would reference structure map, the rest of your code below that stack does not need to know about the DI container becuase its dependencies would be resovled by the main application (E.g MVC) Then the rest of your dependencies etc.. you could seperate the interfaces from the concrete classes, but I would only do that when its required. You could start with a simple MyCompany.MyDivision.Framework.Logging project that contains the ILogger and the SpecialLogger. Becuase the DI container is just references in the top of the stack (e.g the MVC app) it already has references to the components below it, so no circular reference is created. If you find yourself reference the DI container lower down the stack then you may run into problems, there are usually more specific services you can implement for resolving things the DI container could provide. e.g Lets Say you had the Logging assebly, a Domain Layer assembly, and a front end project, and the requirements where for the front end project to have references to the domain layer and logger, but you dont want interdependencies between the two: Then lets imagine you had a bunch of repositories that needed resolving in your domain data access layer, that could be a IRepositoryRegistry interface, but it could be implemented in the app up the stack to look at the DI container to return a repository. There would be no need for your logging assembly to ever use IRepositoryRegistry, so you don't end up with dependencies between those sort of assemblies. James
James Simpson Web Solutions Developer www.methodworx.com
-
The DI framework is usually a component of the application layer (in my experience) e.g If you had an ASP.NET MVC App and you were using structure map, its your front end application that would reference structure map, the rest of your code below that stack does not need to know about the DI container becuase its dependencies would be resovled by the main application (E.g MVC) Then the rest of your dependencies etc.. you could seperate the interfaces from the concrete classes, but I would only do that when its required. You could start with a simple MyCompany.MyDivision.Framework.Logging project that contains the ILogger and the SpecialLogger. Becuase the DI container is just references in the top of the stack (e.g the MVC app) it already has references to the components below it, so no circular reference is created. If you find yourself reference the DI container lower down the stack then you may run into problems, there are usually more specific services you can implement for resolving things the DI container could provide. e.g Lets Say you had the Logging assebly, a Domain Layer assembly, and a front end project, and the requirements where for the front end project to have references to the domain layer and logger, but you dont want interdependencies between the two: Then lets imagine you had a bunch of repositories that needed resolving in your domain data access layer, that could be a IRepositoryRegistry interface, but it could be implemented in the app up the stack to look at the DI container to return a repository. There would be no need for your logging assembly to ever use IRepositoryRegistry, so you don't end up with dependencies between those sort of assemblies. James
James Simpson Web Solutions Developer www.methodworx.com
So just using a very simple example. I would create the UnityContainer and register the FileLogger like this: UnityContainer uc = new UnityContainer(); uc.RegisterType<ILogger, FileLogger>(); Then in the same code block I would resolve the ILogger for the dependent classes like this for an Order class: uc.Resolve<Order>(); To do this I would need to define an Logger property on the order class like this right?: public ILogger Logger { get; set; } From what you are saying it sounds like an important design goal of dependency injection is that a central class does all of the injection and the classes being injected should not need to know about the container. Is this correct?
-
So just using a very simple example. I would create the UnityContainer and register the FileLogger like this: UnityContainer uc = new UnityContainer(); uc.RegisterType<ILogger, FileLogger>(); Then in the same code block I would resolve the ILogger for the dependent classes like this for an Order class: uc.Resolve<Order>(); To do this I would need to define an Logger property on the order class like this right?: public ILogger Logger { get; set; } From what you are saying it sounds like an important design goal of dependency injection is that a central class does all of the injection and the classes being injected should not need to know about the container. Is this correct?
I got the example in my above post to work. Basically, uc.Resolve() returns an Order object with the Order ILogger set to FileLogger. This is great but how can I persist this dependency? In the following example I would expect the FileLogger to be persisted as the ILogger to be used for all instances of the Order object: UnityContainer uc = new UnityContainer(); uc.RegisterType<ILogger, FileLogger>(); uc.Resolve<Order>(); Order o = new Order(); ILogger logger = o.Logger; However, in this example, although the FileLogger is associated with the object returned from the Resolve method, the subsequent Order instantiation does not have a reference to FileLogger (null). This seems to reflect the most typical scenario because the DI should be done once and then code within the Order object will run independently and try to access the Logger from within the Order object. Are there some sort of settings that I'm missing to be able to persist this configuration?
-
I got the example in my above post to work. Basically, uc.Resolve() returns an Order object with the Order ILogger set to FileLogger. This is great but how can I persist this dependency? In the following example I would expect the FileLogger to be persisted as the ILogger to be used for all instances of the Order object: UnityContainer uc = new UnityContainer(); uc.RegisterType<ILogger, FileLogger>(); uc.Resolve<Order>(); Order o = new Order(); ILogger logger = o.Logger; However, in this example, although the FileLogger is associated with the object returned from the Resolve method, the subsequent Order instantiation does not have a reference to FileLogger (null). This seems to reflect the most typical scenario because the DI should be done once and then code within the Order object will run independently and try to access the Logger from within the Order object. Are there some sort of settings that I'm missing to be able to persist this configuration?
In the example you provided you are not initializing the Order class via the container. uc.Resolve() creates an instance of the Order and then resolves its dependencies This is why you would end up with more specialized services to initialize the objects, that are typically implemented with the container. e.g Lets, say Order is an Entity in a domain model, you have several options about how you initialize a new one, a typical way is to have a factory, e.g IOrderFactory.Create(). Lets say for the sake of argument you are using ASP.NET and you are using dependency injection to initialize your controller paramerters via a custom controller factory (if you are unsure about that, basically a DI container is supplying dependencies to Controllers) You would have a dependency to IOrderFactory in your controller constructor which would implement create as: return uc.Resolve(); Your order factory would be injected to your controller, and you can call orderFactory.Create() to get a new instance. Or.. Inject the DI container into your controllers and just always call .Resolve. But I dont like to know about the DI container anywhere in my code, I prefer to have proper named services. e.g IOrderFactory is explicit, it is a Factory for creating Order objects, but by just handing a reference to your DI container everywhere you are actually hiding the dependencies. (e.g from the constructor parameters, it is not obvious what dependencies are going to be used and why) Also - (off topic), with the example you specified above, if Order is an entity in your domain model, and you are attempting to add logging functionality to it, it is better to use a Dynamic Proxy pattern to acheive this (or) Aspect Orientated programming. It is not a dependency of the Order object to have logging functionality, it is more likely a dependency of your infrasturcture. So rather than cluttering up your order object with stuff it does not need, you can inject a Logging mechanism transparently using something like Castle Dynamic Proxy (?) You will still need to get the object from some sort of factory, but it will make your classes much cleaner.
James Simpson Web Solutions Developer www.methodworx.com
-
In the example you provided you are not initializing the Order class via the container. uc.Resolve() creates an instance of the Order and then resolves its dependencies This is why you would end up with more specialized services to initialize the objects, that are typically implemented with the container. e.g Lets, say Order is an Entity in a domain model, you have several options about how you initialize a new one, a typical way is to have a factory, e.g IOrderFactory.Create(). Lets say for the sake of argument you are using ASP.NET and you are using dependency injection to initialize your controller paramerters via a custom controller factory (if you are unsure about that, basically a DI container is supplying dependencies to Controllers) You would have a dependency to IOrderFactory in your controller constructor which would implement create as: return uc.Resolve(); Your order factory would be injected to your controller, and you can call orderFactory.Create() to get a new instance. Or.. Inject the DI container into your controllers and just always call .Resolve. But I dont like to know about the DI container anywhere in my code, I prefer to have proper named services. e.g IOrderFactory is explicit, it is a Factory for creating Order objects, but by just handing a reference to your DI container everywhere you are actually hiding the dependencies. (e.g from the constructor parameters, it is not obvious what dependencies are going to be used and why) Also - (off topic), with the example you specified above, if Order is an entity in your domain model, and you are attempting to add logging functionality to it, it is better to use a Dynamic Proxy pattern to acheive this (or) Aspect Orientated programming. It is not a dependency of the Order object to have logging functionality, it is more likely a dependency of your infrasturcture. So rather than cluttering up your order object with stuff it does not need, you can inject a Logging mechanism transparently using something like Castle Dynamic Proxy (?) You will still need to get the object from some sort of factory, but it will make your classes much cleaner.
James Simpson Web Solutions Developer www.methodworx.com
Thanks James - You know your stuff
-
In the example you provided you are not initializing the Order class via the container. uc.Resolve() creates an instance of the Order and then resolves its dependencies This is why you would end up with more specialized services to initialize the objects, that are typically implemented with the container. e.g Lets, say Order is an Entity in a domain model, you have several options about how you initialize a new one, a typical way is to have a factory, e.g IOrderFactory.Create(). Lets say for the sake of argument you are using ASP.NET and you are using dependency injection to initialize your controller paramerters via a custom controller factory (if you are unsure about that, basically a DI container is supplying dependencies to Controllers) You would have a dependency to IOrderFactory in your controller constructor which would implement create as: return uc.Resolve(); Your order factory would be injected to your controller, and you can call orderFactory.Create() to get a new instance. Or.. Inject the DI container into your controllers and just always call .Resolve. But I dont like to know about the DI container anywhere in my code, I prefer to have proper named services. e.g IOrderFactory is explicit, it is a Factory for creating Order objects, but by just handing a reference to your DI container everywhere you are actually hiding the dependencies. (e.g from the constructor parameters, it is not obvious what dependencies are going to be used and why) Also - (off topic), with the example you specified above, if Order is an entity in your domain model, and you are attempting to add logging functionality to it, it is better to use a Dynamic Proxy pattern to acheive this (or) Aspect Orientated programming. It is not a dependency of the Order object to have logging functionality, it is more likely a dependency of your infrasturcture. So rather than cluttering up your order object with stuff it does not need, you can inject a Logging mechanism transparently using something like Castle Dynamic Proxy (?) You will still need to get the object from some sort of factory, but it will make your classes much cleaner.
James Simpson Web Solutions Developer www.methodworx.com
Hi James - This is the solution that you provided in your last post: "You would have a dependency to IOrderFactory in your controller constructor which would implement create as: return uc.Resolve();" Can you please provide a constructor code block for this? This is the closest constructor I can infer from your post: public OrderController(IOrderFactory creator) { uc.Resolve(); } 1. The factory does the class creation but it's included as a param. So there is another layer of abstraction that sets the appropriate IOrderFactory? What is this additional layer of abstraction and where is it located? 2. So uc.Resolve() should be used to resolve the domain objects used by the controller? I'm assuming that the dependencies are passed down through the interface param? I'm still trying to figure out the pieces and interaction for this.
-
Hi James - This is the solution that you provided in your last post: "You would have a dependency to IOrderFactory in your controller constructor which would implement create as: return uc.Resolve();" Can you please provide a constructor code block for this? This is the closest constructor I can infer from your post: public OrderController(IOrderFactory creator) { uc.Resolve(); } 1. The factory does the class creation but it's included as a param. So there is another layer of abstraction that sets the appropriate IOrderFactory? What is this additional layer of abstraction and where is it located? 2. So uc.Resolve() should be used to resolve the domain objects used by the controller? I'm assuming that the dependencies are passed down through the interface param? I'm still trying to figure out the pieces and interaction for this.
I think my examples are probably more confusing than they should be. if you develop your layers without thinking about the DI layer, just rely on getting dependencies into objects via a constructor, you can add the DI container later. Typically the container would resolve the controller (transparent to your code) and inject an instance of a factory, or repository, or service.. or whatever is needed Then in the example of the IOrderFactory, the create could also be implemented to resolve the Order object from the same container But, if the Order is an Entity you should be using a IOrderRepository to manipulate it, and this can include the factory method Create() The key is to not architect your layers with the DI container in mind, just use the right sort of services to get the job done, at the end of the day they *might* be implemented using a DI container, they might not... if you working with this sort of technology your probably trying to unit test too, so if you get this right, it will probably lead you down the right path anyway. Google sturcture map ASP.NET MVC implementation there are some good articles that demonstrate the idea behind a simple DI container and MVC. Good luck James
James Simpson Web Solutions Developer www.methodworx.com
-
I'm fairly new to dependency injection but it seems like a proper DI implementation will be fairly complex. For example, DI requires a centralized class that manages the configuration and resolves the dependencies at runtime. DI is also based on the concept of using interfaces. For example, a SpecialLogger should use an ILogger interface. The centralized DI manager class will need to register types - for example, associate ILogger to SpecialLogger. SpecialLogger will also need to implement the ILogger interface so SpecialLogger can be used through the DI ILogger interface. Therefore, it seems like a sln using DI will need multiple projects to support DI. Here is an example for logging: * MyCompany.MyDivision.Framework.DI.Management - this would have the DI manager where dependency types are registered and resolved at runtime * MyCompany.MyDivision.Framework.Logging - this would have the implementation of a logging class. The main logging class would need to implement ILogger. * MyCompany.MyDivision.Framework.DI.Interfaces - this would have the ILogger interface. Interfaces would need to be stored in a separate class library from the DI manager because both the DI manager and SpecialLogger use the ILogger interface. Since the DI manager associates SpecialLogger to ILogger a circular reference would be encountered without a separate class library to store the ILogger interface. Does this sound like a reasonable assessment? Like I said I am just learning DI so if you can share any real-world experience with a DI implementation that would be appreciated.
While not incorrect by any means, IoC/DI can be as simple as:
/*
* Simple Inversion of Control/Dependency Injection
*/using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Configuration;
using USCG_SSO.Interfaces;namespace USCG_SSO
{
public class ObjectFactory : IObjectFactory
{
public ObjectFactory() { }// Create an instance of an object public T getInstance() { return getInstance(null); } // Overload create instance of an object using creation parameters public T getInstance(object\[\] initializationParameters) { NameValueCollection appSettings = ConfigurationManager.AppSettings; Type type = Activator.CreateInstance(typeof(T), initializationParameters).GetType(); // Any special initialization for an object should be placed in a case statement // using that object's fully qualified type name if (initializationParameters == null) { switch (type.ToString()) { case "USCG\_SSO.ServiceUser": NameValueCollection appSettings = ConfigurationManager.AppSettings; initializationParameters = new object\[\] { appSettings\["ADUserID"\], appSettings\["ADUserPassword"\], appSettings\["ADFieldName"\] } break; case "USCG\_SSO.ActiveDirectory" initializationParameters = new object\[\] { new ObjectFactory().getInstance(), new ObjectFactory().getInstance() } break; default: break; } } return (T)Activator.CreateInstance(typeof(T), initializationParameters); } }
}
Assuming: USCG_SSO.ActiveDirectory object requires a ServiceUser object and a CurrentUser object to be passed in it's constructor, and USCG_SSO.ServiceUser object requires values retreived from the .config file in it's constructor. If you call
IActiveDirectory ADObject = new ObjectFactory().getInstance();
You would obtain an ActiveDirectory object complete with all of it's dependencies. Now, granted, this isn't as "fancy" or extensible as an actual IoC framework (there's no registration of dependencies, auto-resolution, etc.), it is, however, a complete, very simple IoC/DI implementation.
Kevin Rucker, Application Programmer QSS Group, Inc. United States Coast Guard OSC Kevin.D.R