Can someone please explain to me the notion of a Unity Container like I'm a 6 year old kid? How does it work and what does it do?
This is a more technical description of the background, I hope you still find it useful.
Generally put, it is a DI (dependency injection) container.
Given the following class:
public class Sample
{
Service a;
public Sample()
{
a = new Service();
}
}
The problem with that is that it initializes its own version of Service, making it very hard to adjust for code changes (ie. if you want to exchange Service with something different). Also it makes testing difficult.
To resolve that, don't actually create it yourself, but get it from the outside:
public class Sample
{
Service a;
public Sample(Service aService)
{
a = aService;
}
}
Now you have taken the creation away from the class you can just put it in there from the outside, increasing testability and maintainability. However, you still have a dependency on the class Service. You aren't really interested in that specific class, but in the behaviour it offers - so you make in interface out of it.
public class Sample
{
IService a;
public Sample(IService aService)
{
a = aService;
}
}
Now, you can replace the service with anything you like. For example, you have a class getting data from a server using a service. Now, you want to test only the data parsing and not the data fetching service - just create a class implementing the interface, serving static data - done!
Now, Unity comes into play. At the moment, you have to resolve the dependencies yourself. What unity does is simple - it takes all classes that have dependendencies and resolves those - so you can just call (pseudocode, I don't know unity):
UnityContainer uc = new UnityContainer();
var a = uc.GetService<IService>();
And it gets you the readily useable class.
What do we have achivied by that?
the code is more maintainable because you don't rely on specific types
the code is more testable
the application is easily expandable
As a summary: it helps creating better applications faster.
Unity Container is like a jar full of cookies , when you need a cookie you just ask jar to give you a cookie.
Each cookie is having some virtues like you can have a cookie but you can't eat it because it is very hard to eat (something like singleton)
when your mom creates a new cookie , she just put that cookie in the jar rather than giving you directly!
I recommend you to watch Mike Taulty's Prism video series
The first two chapters will answer your question, and you can watch the other chapters to learn Prism (although its version 2 and quite old, the basic principles remains the same...)
Good luck :)
Related
I am reading the book You, I and ReactiveUI and my question relates to the source code for the book at https://github.com/kentcb/YouIandReactiveUI. The versions of ReactiveUI and Splat have changed since the code was published and one portion of the code cannot be duplicated in the current versions. I have contacted the author and am still waiting on a response as of this time of posting this question, and so I am submitting this question here.
In App.xaml.cs there is a call to a Registrations.cs class that passes the current mutable dependency resolver:
public App()
{
this.autoSuspendHelper = new AutoSuspendHelper(this);
Registrations.Register(Splat.Locator.CurrentMutable);
}
In the Registrations.cs class, there is a line that takes that IMutableDependencyResolver and calls GetService:
public static void Register(IMutableDependencyResolver container)
{
...
var defaultViewLocator = container.GetService<IViewLocator>();
...
}
I, too, would like to get the IVewLocator service, but IMutableDependencyResolver no longer has a GetService method.
So my question is, how should this code be modified to have the same functionality?
The Splat.Locator.Current is an IReadonlyDependenyResolver and that does have a GetService method. Should that be used instead? I wasn't sure if I should change to using Splat.Locator.Current in case there was a reason that Splat.Locator.CurrentMutable was used and wanted to make sure that if I changed to using Splat.Locator.Current that it would not introduce anything unexpected.
UPDATE:
Just want to add that, armed with the knowledge from DPVreony's answer that it is typically the same class implementing the two interfaces, I was able to implement some later lines in the Registrations.cs class that I needed.
So, further in that class, there are some lines that register constants. These needed the mutable dependency resolver. So you can just pass both the read only and mutable into the Registrations class and use them where needed, as shown below:
public static void Register(IReadonlyDependencyResolver container, IMutableDependencyResolver mutableContainer)
{
...
var defaultViewLocator = container.GetService<IViewLocator>();
...
mutableContainer.RegisterConstant(viewLocator, typeof(IViewLocator));
...
var defaultActivationForViewFetcher = container.GetService<IActivationForViewFetcher>();
...
mutableContainer.RegisterConstant(activationForViewFetcher, typeof(IActivationForViewFetcher));
mutableContainer.RegisterConstant(activationForViewFetcher, typeof(IForcibleActivationForViewFetcher));
}
And then call the method like so:
Registrations.Register(Splat.Locator.Current, Splat.Locator.CurrentMutable);
There was a change in Splat due to how some DI containers behave with registering services (i.e. they keep re-initializing). So get functionality was split off onto the IReadonlyDependenyResolver exposed by Splat.Locator.Current
It was to encourage the mindset of use the MutableLocator to get everything in place and then after that you should only ever need to read using Splat.Locator.Current so you're fine to use it. Typically it's the same class implementing the 2 interfaces, so it's a semantic change to reduce risks of tearing down the locator by mistake.
So in short yes Splat.Locator.Current is for GetService
Hope that all makes sense.
I come across this regularly when refactoring code. Say I have a base class and I read some configuration parameters and stuff them into properties like this
public BaseClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
And then I call a method in another class like this
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod(_property1, _property2, _property3);
Is it better to do that? What if I only needed the AppSettings values inside of the OtherClass class? then I could just load them up as private props and initialize them in the constructor and the referencing class/caller wouldn't need to be concerned with the settings.
public OtherClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
My implementation would then simply be
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod();
This one bugs me but I am not really sure why. Which is a better practice and why? And I apologise I am missing something obvious. It happens sometimes lol.
Thanks -Frank
In my view, it depends on what goal of your class.
If class belongs to domain classes, so there is no need to have a dependency to ConfigurationManager class. You can create a constructor and supply necessary data:
public class FooClass()
{
public Property1 {get; private set;}
public FooClass(string property1)
{
Property1 = property1;
}
}
If FooClass belongs to Service Layer, then, in my view, it is eligible to have a dependency to ConfigurationManager class.
I can't really comment on "better" as that's quite subjective, but it's at the very least factual to say that passing the parameters into the method, rather than having the method go and get them itself, is a form of dependency injection. Dependency injection has advantages in that it reduces the number of things the class has to know how to do/reduces the number of other classes any given class needs to do its work. Typically in OO design we look for ways to reduce the dependencies a class has on other classes. You might also see the concept referred to in general as low coupling. Classes that are not highly coupled to other classes are easier to reuse as independent modules within multiple programs
In your example, OtherClass (and/or BaseClass) needs to know what a ConfigurationManager is, which means it needs a reference to its namespace, needs to have system.configuration.dll available on the target etc just so that it can go and get some basic things (strings) that contain info necessary to do its work. If you instead give the strings to the method then it can do its work without knowing what a ConfigurationManager is - you can use it in an app that doesn't even have a ConfigurationManager anywhere, maybe because it gets its config from a database or perhaps it's part of a unit test that gets some contrived data directly from hard coding to ensure a given result is always obtained
When you're down with the concept that the data a class needs to do its work can come from above it starts to make more sense why systems that pass data around like this can work with an inversion-of-control container; essentially software that creates instances of objects for you according to some preconfigured rules about where to get the data that should be passed in. An IoC container can look at an object and decide what arguments to pass to (e.g. its constructor) based on a consistent set of rules, and take another step towards removing dependencies by further reducing use of the word "new". Think of it like writing a config file to describe which of your objects need what instances of other classes to do the work. You craft your IoC container setup so it makes one IniFileConfigSettingsProvider instance and then provides that instance to any object that needs some kind of IConfigSettingsProvider to do its work. Later you switch away form ini files and go to Xml files. You create a class called XmlFileConfigSettingProvider, register it with the IoC and it becomes the new instance that is passed to any class needing an IConfigSettingsProvider. Critically, you made another class, registered it with the IoC and then it gets used throughout your program but you never made an instance of it yourself
If you ever heard the phrase "new is glue" concepts like this are generally what it alludes to - when your OtherClass says var x = new ConfigurationManager... x.Settings["a"].... the use of the word new has suddenly hard wired it to needing a ConfigurationManager; it can't function without knowing what it is. The strive these days is generally to have a class accepting a "passed-in provider of settings that complies with some interface" or "passed-in primitives that are settings" - things that are either implementation specific but obey a generic interface, or ubiquitous in the language and need no special imports respectively. Perhaps either of your mentioned approaches bug you because deep down you feel that neither of them need to depend on ConfigManager; whether they both need settings or not, they can get them passed in, from something higher up the chain that should be making the decisions as to what settings to use
There will be pros and cons of every design and coding choice. As they say, same pattern may not fit everyone. So one has to customize based on need.
Mainly, decision should be based on use cases of your application. Let me provide few scenarios to describe it. Suppose items configured in AppSettings will not change in life-time of the your application then you can have an approach in which dependencies with AppSettings are least. In particular an approach as var foo = otherClass.SomeMethod(_property1, _property2, _property3);. This matches with OOD principles as classes will focus on business logic.
But if you see add/modifying/deleting items (even in rare situations) during life time then above approach would be difficult to maintain. For example without restarting your application/WebServer if AppSettings needs to be reloaded based on certain conditions. One may argue why such settings will be kept in AppSettings, which is very valid too. If your application demands such scenarios then it would be better to use ConfigurationManager.AppSettings without worrying about dependencies. One can opt to extend it have wrapper class (Singleton pattern) to manage and provide access to ConfigurationManager.AppSettings.
This is an extension to the question Why do I need an IoC container as opposed to straightforward DI code?
I've been learning Ninject and came up with the following example, the example goes through the manual way of doing DI and the Ninject way of doing DI:
class Program
{
static void Main(string[] args)
{
NinjectWay();
ManualWay();
Console.ReadKey();
}
private static void ManualWay()
{
Console.WriteLine("ManualWay***********************");
IWeapon sword = new Sword();
Samurai samurai = new Samurai(sword);
Console.WriteLine(samurai.Attack("ManualWay..."));
// change weapon
IWeapon dagger = new Dagger();
samurai.Weapon = dagger;
Console.WriteLine(samurai.Attack("ManualWay..."));
IWeapon weapon = new Shuriken();
IWarrior ninja = new Ninja(weapon);
Console.WriteLine("Manual way.. inject shuriken when a ninja. " + ninja.Weapon.Name);
IWarrior ninja2 = new Ninja(weapon);
}
private static void NinjectWay()
{
Console.WriteLine("NinjectWay***********************");
IKernel kernel = new StandardKernel();
kernel.Bind<IWeapon>().To<Sword>();
var samurai = kernel.Get<Samurai>();
Console.WriteLine(samurai.Attack("NinjectWay..."));
kernel.Rebind<IWeapon>().To<Dagger>();
samurai = kernel.Get<Samurai>();
Console.WriteLine(samurai.Attack("NinjectWay..."));
kernel.Bind<IWeapon>().To<Shuriken>().WhenInjectedInto<Ninja>();
var ninja = kernel.Get<Ninja>();
ninja.OffHandWeapon = new ShortSword();
Console.WriteLine("Conditional Injection..."+ninja.Weapon.Name);
Console.WriteLine("Conditional Injection: OffhandWeapon = " + ninja.OffHandWeapon.Name);
var ninja2 = kernel.Get<Ninja>();
Console.WriteLine("Conditional Injection..." + ninja2.Weapon.Name);
Console.WriteLine("Conditional Injection: OffhandWeapon = " + ninja2.OffHandWeapon.Name);
Console.WriteLine("");
}
}
I hear the benefits happen when the scale of the project increases but I'm not seeing it. Help me understand this better. Provide more examples in C#/Ninject and help me understand where the benefits really become apparent.
Unlike the other answers suggest Ninject isn't mainly about making your code more testable. It's Dependency Injection that makes your code more testable! Dependency Injection can be used without an IoC container by creating everything in facotries. But sure, beeing able to replace some parts easily for Integration Tests (don't use Ninject in unit tests) is a nice side effect.
IoC containers like Ninject are mainly about putting your classes together to a working software. In small projects this can easily be done using some factories. But as your application grows the factories get more and more complicated. Imagine an application that has various services some of them are reused others are newly created for every usage. Some of the services are also used by several components.
If you are using a IoC container you have to define exactly once how you get the service instance and what's its lifecycle. On the other hand in a factory you have to specify how you get the instance for every class that needs an instance (e.g. new MyServiceFactory().CreateInstance()). Furthermore, you have to control the lifecycle manually.
This means as the project grows the configuration of an IoC container grows linear together with the project size. But a factory on the other hand grows more exponentional like as there are services that are used throughout the application (e.g. user auth).
BTW: Your example isn't very good because Rebinding isn't a common action. Usually the configuration is done only once at application startup.
GREAT QUESTION!
The BIG BIG win IMHO is when your code that asks for instantiations doesn't know or care what the actual implementations are. This is most evident in mocking - your mocking framework can configure Ninject to return mocked Ninja's, Sword's, and Samarai's that implement behavior your expect in completely different ways.
I have a repositry layer, for example, that depends on IoC to get access to a data-store. For testing, that data-store is a hand-constructed collection of objects. For remote access, the data-store consumes web services. Locally, it's SQL. The repository simply asks for the IDataStore from the IoC and gets whatever was configured to serve up.
Does that help?
One benefit comes in testing.
You can bind Sword to IWeapon in your production code, and FakeSword to IWeapon in your test assembly. This is useful when you need to test something that has a dependency on IWeapon but you don't actually want a real sword.
For example, instead of Sword and IWeapon you have IDataContext and DataContext. Great in your production code when you need to connect to a DB. But for unit tests you probably don't want to actually hit the database for a variety of reasons (performance, inconsistent data etc.) So you'd wire up a FakeDataContext to your IDataContext. Now you've got some control to simulate DB activity for testing.
The main advantage Ninject has over you doing it manually is that somebody else has done a lot of the abstracting for you. Clearly you could reproduce a similar thing by writing similar code to Ninject (something for creating the objects based around interface types), which would allow you to separate your object construction from your object logic but Ninject (and other libraries) have all ready done a lot of the hard work for you so unless you're going to add something new why would you want to create it all again?
The comparison you've got in your question isn't really representative of the way I'd expect Ninject to be used. You're binding and rebinding in the same method that's using the objects. I'd expect the container setup to be done somewhere else. This allows you to change the construction (so that for example it's easier to test by creating mock objects) without altering the code that actually uses the constructed object.
I'm working on a project that's using the MS Application Blocks. I see the 'Unity' dll is available to me. It's version 1.1 by the way. How can I use dependency injection here?
I have a class
public class ScheduleDataDetailsDC
{
public int ScheduleID;
public List<ScheduleRateLineItem> MinRateList;
public List<ScheduleRateLineItem> MaxRateList;
public List<ScheduleRateLineItem> VotRateList;
public List<ScheduleLOSRateDC> LosRateList;
public List<ScheduleRateParamsDC> RateParams;
}
So when I new it up I am doing this...
new ScheduleDataDetailsDC{
LosRateList = new List<ScheduleLOSRateDC>()
, MaxRateList = new List<ScheduleRateLineItemDC>()
, MinRateList = new List<ScheduleRateLineItemDC>()
, RateParams = new List<ScheduleRateParamsDC>()
, VotRateList = new List<ScheduleRateLineItemDC>()
}
Can Unity 1.1 Help me in anyway here? I would like to just be able to use var x = new ScheduleDetailsDC(), and those 5 inner lists be initialized for me. Can Unity do anything for me here? Please note I've never used DI before.
Thanks for any pointers,
~ck in San Diego
The best thing to do would be to initialise the lists in the constructor and deny direct access to them from other classes by making them into properties:
public class ScheduleDataDetailsDC
{
public ScheduleDataDetailsDC()
{
this.MinRateList = new List<ScheduleRateLineItem>();
//inialise other lists
}
public List<ScheduleRateLineItem> MinRateList { get; private set; }
...
}
It doesn't seem as though dependency injection can really be of use here since the class seems to be a simple data container, although it's difficult to tell without more context.
Yes Unity can help you, but I think it's not the case. You can just initialize your lists incide your object giving them default instances, Unity as any other IoC container shouldn't be used as a simple object builder (despite it could).
I'm not sure specifically what the details of the 1.1 release of Unity are, but generally speaking whenever you are using an Inversion of Control Container, you have to go through the following steps:
Register the types your IoC container (Unity in your case) knows about. This includes all of the main types that you plan to request, plus all of the dependent types. In your case you will need to let it know about ScheduleDataDetailsDC, and what, exactly needs to go into each of the lists that are considered dependencies
Your types should specify all of the required dependencies as constructor arguments. This is what the IoC Container will look at to determine what needs to be injected. If you have optional dependencies then you can use Property Injection to support that (if your IoC container supports it, which I think Unity does)
You must request an instance of your registered type from the container. How exactly you do this depends on you container. There should be a method like Get<T>() or Resolve<T>. Generally your going to request instances of the "Highest Level" classes, i.e the ones that are used somewhere near the entry point for your software. If you do this, and you have applied Dependency Injection for all dependent classes down the line (and you've correctly registered all of the dependent types) you should get an object with all of it's dependencies supplied, and likewise all of that objects dependencies should be supplied, and on down the line.
You also tend to see Interfaces used in conjunction with IoC a lot since you can bind a concrete type to the interface type, and then specify that interface as your dependency. This allows you to apply business rules and configuration values during the binding process that will give you the ability to use different concrete implementations in cases where you would need to do such a thing.
So given all of this, it's hard to say exactly what would be involved in utilizing Unity in the situation you've outlined above. Firstly you would need to register ScheduleDataDetailsDC, but to get the dependencies in place you would also need to register each of the List types, or more specifically each concrete object that would go in each list (and then, of course all of the dependencies for those classes). Since I'm not really sure what the roles of those lists are, it's hard for me to say how you could go about doing that (or even if you could go about doing that).
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.