Inversion of control for your Inversion of control container? - c#

I've recently had to update a relatively large control library that uses Ninject 1.0 to Ninject 2.0 to help resolve some issues I had with 1.0. The update has gone well and I think Ninject 2.0 is a lot quicker.
However to try and avoid this problem in the future I have created my own interface for injecting fields and properties (which will essentially call methods on the IOC container I wish to use within the current web application). So now my control library is independant of any particular IOC container which will speed up any changes in that area in the future.
I was wondering has anyone else has done the same thing?
I'm happy with what it has achieved but ideally I would like to update it. In my controls I create these injected fields often as protected and set them in the constructor for that control.
IBlogService _blogService = null;
IEmailService _emailService = null;
public Templates_BlogTemplate()
{
Inject(ref _blogService);
Inject(ref _emailService);
}
The problem I have with the above is that I have to use "ref" on all objects to actually set the property and I cannot use that on properties directly.
I would prefer to do something along these lines but I don't think it is possible.
IBlogService _blogService = null;
IEmailService _emailService = null;
public Templates_BlogTemplate()
{
Inject(_blogService, _emailService);
}
Has anyone got any ideas of how to neaten the code up or make it work in a cleaner way? I also would want to avoid attributes so it forces the developer to make a decision to inject the variable at a certain point within the control.
All thoughts and feelings are welcome.
Thanks

Support property injection, and inject dependencies to "this".
In my case, I have a base class that calls StructureMap.BuildUp(this), and the user control would have properties like:
public IBlogService _blogService{get;set;}
public IEmailService _emailService{get;set;}
The only line specific to structuremap I have is in the base class. If ninject allows you to do this, then you can call your code handing it the control instance, and let it inject the properties based on its configuration.

You may want to look at IServiceLocator as described by Glenn Block
It's a shared interface that can be used to take advantage of IoC without taking a hard dependency on the container.

Related

Static class to dependency injection

The application I'm trying to get to work uses MVVM. The biggest part of this post is an explanation of what I tried and what I got working. The question is near the bottom of the post. The used Localizer class is only used here as an example and can easily be replaced with another class.
I have a class library with a Localizer class. This purpose of this class is to change the language of the application on the fly, without having to restart the application. The `Localizer has to be instantiated before it can be used but once instantiated, should be usable in the entire application. (The class uses the application resources to localize the application.)
My first approach I could think of is making the Localizer a public static class with a public static void Initialize method. This way I could initialize the Localizer like this
Localizer.Initialize(/* Needed arguments here */);
on the application level and use it wherever I want in either my class library or application like this
string example = Localizer.GetString(/* A key in the resource dictionary */);
Considering the class library is written by me (only I have the source code) and used by other people who have no clue about the source code (they only know what the class library can do), I would have to explicitly state in some sort of "How to use this class library" that they need to call Localizer.Initialize on the application level in order to use it everywhere in their application.
After doing some research a lot of people state that this is a bad practice and suggest investigating what Dependency Injection (DI) and Inversion of Control (IoC), so I did. I learned that DI is doing about the same as my first approach but remove the static stuff, use Localizer.Initialize as the constructor and inject the instantiated class in my other classes.
So the second approach is dependency injection and this is where I'm stuck. I managed to let my application compile with a single MainWindowView and MainWindowViewModel with the following code:
protected override void OnStartup(StartupEventArgs e)
{
ILocalizer localizer = new Localizer(Current.Resources, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, "Languages", "Language", "en");
var mainWindowViewModel = new MainWindowViewModel(localizer);
var mainWindowView = new MainWindowView { DataContext = mainWindowViewModel };
mainWindowView.Show();
base.OnStartup(e);
}
What the above code does is, is inject the localizer into MainWindowViewModel. This way no additional code is added to the MainWindowView code behind and has the view a view model bound to.
In MainWindowViewModel the constructor is like this (note that the message box is called somewhere else but was moved here to minimize the code):
ILocalizer _localizer;
public MainWindowViewModel( ILocalizer localizer)
{
_localizer = localizer;
MessageBox.Show(_localizer.GetString(/* A key in the resource dictionary */));
}
The above code is still compiling and running fine without exceptions. The problem occurs when I have either UserControls in my class library with a view and view model that also require the localizer instance.
I think I have a solution for when I have a UserControl in my application assembly but it feels like it is more 'complex' then when I would use a static class. I usually just bind the view model of a UserControl to the view in its code behind. This way I can simply add the UserControl to my .xaml code like this <local:UserControl1 /> without a lot of extra hustle. This way the view model parent view model doesn't have to be concerned about child view models.
With DI I would do something like this in my parent (the child would be the same as in the previous block of code):
View
<n:UserControl1 DataContext="{Binding UC1ViewModel}" />
ViewModel
public UserControl1ViewModel UC1ViewModel { get; set; }
ILocalizer _localizer;
public MainWindowViewModel(ILocalizer localizer)
{
_localizer = localizer;
UC1ViewModel = new UserControl1ViewModel(localizer);
}
The above is still all working fine, no problems so far. The only thing that changed is that the DataContext is set in the parents view and the content of the DataContext is set in the view model of the parent.
The question
I also have several UserControls in my class library. These can be used by the users of the class library but they can't alter them. Most of these UserControls are some fixed pages that display information about a person, car, etc. The intention is that, for example the label with the name of the person is "Name" in English, "Naam" in Dutch, etc. (which are all declared in the view and are working fine) but there is also text in the code behind that has to be localized and this is where I'm stuck.
Should I approach the problem the same way as I'm doing with a UserControl in my applications assembly? This feels really counterproductive if let say 20+ of these UserControls are used in a single parent view.
I also feel that I'm not implementing DI 100% correctly.
Problem
DI is not as simple as you've made it look. There are DI frameworks out there which take care of the DI concern, and they are mature pieces of software.
You can't really do DI yourself without designing a DI container because of the way DI should work
DI solves a few problems, a couple of the main ones are:
IoC - ensuring that components aren't tightly coupled by moving the resolution and provision of dependencies outside of the component classes
Lifetime scope - ensures that components have a well defined lifetime/lifecycle and that they are correctly instantiated and disposed of at key points in your application
How does it look?
You shouldn't even see the container! - you should only see components dependencies and the rest should look like magic...
DI containers should be very transparent. Your components and services should require their dependencies simply by specifying what the dependencies are (in their constructors)
What's my current problem?
You don't want to be having to manually wire up sub-dependencies with code like this:
public MainWindowViewModel(ILocalizer localizer)
{
_localizer = localizer;
UC1ViewModel = new UserControl1ViewModel(localizer); // <-- ouch
}
There are a number of problems with the above:
You are making the MainWindowViewModel responsible for creating the UC1ViewModel and managing the lifetime of the object (this isn't always a bad thing as sometimes you want to manage the lifetime of an object in a particular component)
You are coupling the implementation of the MainWindowViewModel to the constructor implementation of UserControl1ViewModel - if you require another dependency in UserControl1ViewModel, suddenly you have to update MainWindowViewModel to inject that dependency, cue a lot of refactoring. This is because you are instantiating the type yourself instead of letting a container do it.
How do containers prevent code like the above?
With any container you should be registering components
The container will track the list of possible components and services and use this registry to resolve dependencies.
It also tracks the dependencies lifecycle (singleton, instanced etc)
Ok I've registered everything, what next?
Once you have registered all your dependencies, you then resolve your root component from the container. This is known as the composition root and should be the 'entry point' for your application (usually the main view or main method).
The container should take care of wiring up and creating the dependencies for everything that stems from that composition root.
Example:
(Pseudo code)
public class ApplicationBootstrapper
{
private IContainer _container;
public ApplicationBootstrapper() {
_container = new SomeDIContainer();
_container.Register<SomeComponent>().AsSingleton(); // Singleton instance, same instance for every resolve
_container.Register<SomeOtherComponent>().AsTransient(); // New instance per resolve
// ... more registration code for all your components
// most containers have a convention based registration
// system e.g. _container.Register().Classes().BasedOn<ViewModelBase> etc
var appRoot = _container.Resolve<MainWindowViewModel>();
appRoot.ShowWindow();
}
}
Now when your application runs, all dependencies are injected into the root and all dependencies of the root and so on
Your MainWindowViewModel could then specify a dependency on the UC as such:
public MainWindowViewModel(UC1ViewModel vm)
{
}
Notice how the MainWindowViewModel no longer needs an ILocalizer instance, it will be resolved and injected into the UC1ViewModel for you (unless of course you need it).
Couple of points to note
You should not pass an instance of the container around. If you are referencing the container in your application code anywhere other than during application startup you are probably doing something wrong
Deferred resolution of dependencies is usually achieved with factories (types that are designed specifically to resolve from the container on behalf of your components). The factory should be injected into the component and the component can then call the factory to get the instance it needs. This also allows you to pass arguments to the dependency.
Use SOLID principles, depend on abstractions not concrete classes. This way it's much easier to swap out components if you decide to change the way something works (you just change the registration code to use a different concrete class that implements the same interface, et voila, no refactoring the app)
Anything else
This is by no means a concise view of DI, there is a lot to consider, but hopefully it will get you started. As Steven mentioned, if you are planning on redistributing the library you should read up on best practices.
The original post on dos/dont's is here:
Dependency Inject (DI) "friendly" library
Which DI container should you use?
The world is your oyster. I'm a fan of Castle Windsor - it's not the fastest (I can't think of an app I've written where I've ever needed component resolution to be ninja fast...), but it's certainly fully featured.
Update: couple of non queries I didn't really address
Plugins
Castle Windsor has plugin capabilities built in - so you can drop a DLL into your application directory which adds functionality to your application by registering components with the container. Not sure if this applies to your UC class library or not (you could just make the app depend on it unless it needs to actually be a plugin)
Other stuff
There are also quite a lot of MVVM frameworks with several different approaches on view/viewmodel resolution (viewmodel-first, view-first, hybrid approaches).
You may want to consider using one of these to help guide you in structuring your application if you are not already using one (it doesn't sound like you are).
Have a look at this article on localization in WPF applications:
http://www.codeproject.com/Articles/299436/WPF-Localization-for-Dummies
Your localization can be handled via resource assemblies for each language you need to support and the correct one will be used at run-time based on the current culture - or a fallback culture. Your view models can reference the resources and shouldn't care about the specific locale.

How to change the scope of an existing binding in Ninject

In one module, I have a binding set up for an object. There are two other modules: a testing module and a web module. The web module wants that binding to be in request scope, and the testing module wants that binding to be in singleton scope. Right now, we are just duplicating the entire binding and adding the appropriate scope. Is there a better way to do this? I am looking for a way that I can make the binding itself (it's a ToMethod binding) in the one module, and then just have the testing and web modules just change the scope on that binding.
This scenario is not specifically supported by ninject, and most likely also not by any other IoC.
Especially Scoping, but there also may be other things like context parameters and the way one resolves certain types and configuration, is something which is often dependent on the application / composition root.
But of course you can make use of the "normal" programming principles to lessen the burden, if you so wish. But i would not really recommend it because while you may make the scope easily configurable it will make other things more complicated and harder to maintain. For example:
public class ConfigurableScopeBindingModule : NinjectModule
{
private readonly Action<IBindingInSyntax<object>> scopeConfigurator;
public ConfigurableScopeBindingModule(Action<IBindingInSyntax<object>> scopeConfigurator)
{
this.scopeConfigurator = scopeConfigurator;
}
public override void Load()
{
this.BindAndApplyScoping(x => x.Bind(typeof(string)).ToSelf());
}
private void BindAndApplyScoping(Func<IBindingRoot, IBindingInSyntax<object>> binding)
{
this.scopeConfigurator(binding(this));
}
}
and use like:
IKernel.Load(new ConfigurableScopeBindingModule(x => x.InSingletonScope()));
Using Ninject, simply use the Bind<T>().ToSelf() - and then add whatever scope you want (Bind<T>().ToSelf().InRequestScope(), for example).

How to access Ninject.Kernel without using Service Locator pattern

I have read dozens of posts regarding this topic, without finding a clear guideline of how to access the Ninject.Kernel without using the Service Locator pattern.
I currently have the following in the classes that need to use CustomerBusiness (which is my service) and it works fine, but I am well aware that it is not the recommended way of doing it.
private CustomerBusiness _customerBusiness;
private ICustomerRepository CustomerRepository
{
get { return NinjectWebCommon.Kernel.Get<IAccountRepository>(); }
}
private CustomerBusiness CustomerBusiness
{
get
{
if (_customerBusiness == null)
{
_customerBusiness = new CustomerBusiness(AccountRepository);
}
return _customerBusiness;
}
}
public Customer GetCustomer(int id)
{
return CustomerBusiness.GetCustomer(id);
}
This is the Kernel property accessed in the code above:
public static IKernel Kernel
{
get
{
return CreateKernel();
}
}
I've read many suggestions about using a factory for this, but none of them explain how to use this factory. I would really appreciate if anyone could show me the "CustomerFactory" or any other recommended approach including how to use it.
Update
I am using ASP.NET Web Forms and need to access CustomerBusiness from CodeBehind.
Solution
The final solution that I found to be working, was the answer with the most votes found at this post:
How can I implement Ninject or DI on asp.net Web Forms?
It looks like this (Note inheritance from PageBase, which is part of Ninject.Web - that is the key!):
public partial class Edit : PageBase
{
[Inject]
public ICustomerBusiness CustomerBusiness { get; set; }
...
The accepted answer below indirectly lead me to find this solution.
Since you're using NinjectWebCommon, I assume you have a web application of some sort. You really should only access the Ninject kernel in one place - at the composition root. It is the place where you are building the object graph and the only place you should ever need an access to the IoC container. To actually get the dependencies you need, you typically employ constructor injection.
In case of MVC web applications, for example, you have a controller factory using the Ninject kernel and that's the only place which references it.
To expand on your particular situation, your class would accept ICustomerBusiness in its constructor, declaring that it needs an instance of ICustomerBusiness as its dependency:
class CustomerBusinessConsumer : ICustomerBusinessConsumer
{
private readonly ICustomerBusiness customerBusiness;
public CustomerBusinessConsumer(ICustomerBusiness customerBusiness)
{
this.customerBusiness = customerBusiness;
}
...
}
Now, whichever class uses ICustomerBusinessConsumer as its dependency, would follow the same pattern (accepting an instance of ICustomerBusinessConsumer as its constructor parameter). You basically never construct your dependencies manually using new (specific exceptions aside).
Then, you just have to make sure your classes get their dependencies and it's this composition root where you do this. What exactly is composition root depends on the type of an application you are writing (console application, WPF application, web service, MVC web application...)
EDIT: To get myself familiar with the situation in the ASP.NET WebForms realm
I had to look up the details since I've never used it. Unfortunately, WebForms require you to have a parameterless constructor at each of your Page classes, so you can't use constructor injection all the way from the top of the object graph down to the bottom.
However, after consulting Mark Seeman's chapter on composing objects in WebForms, I can rephrase how to deal with this framework's inefficiency, while still acting in line with good DI practices:
Have a class responsible for resolving the dependencies, using the Ninject's kernel you have set up. This may be a very thin wrapper around the kernel. Let's call it DependencyContainer.
Create your container and save it in the application context, so that it's ready when you need it
protected void Application_Start(object sender, EventArgs e)
{
this.Application["container"] = new DependencyContainer();
}
Let's suppose your page class (let's call it HomePage) has a dependency on ICustomerBusinessConsumer. Then DependencyContainer has to allow us to retrieve an instance of ICustomerBusinessConsumer:
public ICustomerBusinessConsumer ResolveCustomerBusinessConsumer()
{
return Kernel.Get<ICustomerBusinessConsumer>();
}
Than in the MainPage class itself, you will resolve its dependencies in the default constructor:
public MainPage()
{
var container = (DependencyContainer) HttpContext.Current.Application["container"];
this.customerBusinessConsumer = container.ResolveCustomerBusinessConsumer();
}
Few notes:
having the dependency container available in the HttpContext must not be tempting to consider it a service locator. In fact, the best practice here (at least from the standpoint of being true to DI) is to have some kind of "implementor" classes to which you will relay the functionality of your page classes.
For example, each action handled by MainPage will be only relayed to its implementor class. This implementor class will be a dependency of MainPage and, as all other dependencies, will be resolved using the container.
The important part is that these implementor classes should be in assemblies not referencing the ASP.NET assemblies and thus without a chance to access the HttpContext
having to write so much code to achieve this is certainly not ideal, but it is only a consequence of the framework's limitation. In ASP.NET MVC applications, for example, this is dealt with in a much better way. There you have single point where you can compose the object graphs and you don't have to resolve them in each top-level class as you have to in WebForms.
the good thing is that while you have to write some plumbing code in the page class constructors, from there down the object graph you can employ constructor injection
Constructor injection is the preferred method for DI with ninject, however it also supports property injection. Take a read of the ninject page around injection patterns here https://github.com/ninject/ninject/wiki/Injection-Patterns.
Both of these are injection patterns unlike service location which is request based, not really injection at all.
The flipside of injection is that you need to control construction. When using MVC all of the wiring to do this is built into the MVC ninject package on nuget

What is an IOC container actually doing for me here?

So I've refactored completely to constructor injection, and now I have a bootstrapper class that looks similar to this:
var container = new UnityContainer();
container.RegisterType<Type1, Impl1>();
container.RegisterType<Type2, Impl2>();
container.RegisterType<Type3, Impl3>();
container.RegisterType<Type4, Impl4>();
var type4Impl = container.Resolve((typeof)Type4) as Type4;
type4Impl.Run();
I stared at it for a second before realizing that Unity is really not doing anything special here for me. Leaving out the ctor sigs, the above could be written as:
Type1 type1Impl = Impl1();
Type2 type2Impl = Impl2();
Type3 type3Impl = Impl3(type1Impl, type2Impl);
Type4 type4Impl = Impl4(type1Impl, type3Impl);
type4Impl.Run();
The constructor injection refactoring is great and really opens up the testability of the code. However, I'm doubting the usefulness of Unity here. I realize I may be using the framework in a limited manner (ie not injecting the container anywhere, configuring in code rather than XML, not taking advantage of lifetime management options), but I am failing to see how it is actually helping in this example. I've read more than one comment with the sentiment that DI is better off simply used as a pattern, without a container. Is this a good example of that situation? What other benefits does this solution provide that I am missing out on?
I have found that a DI container becomes valuable when you have many types in the container that are dependent on each other. It is at that point that the auto-wire-up capability of a container shines.
If you find that you are referring to the container when you are getting object out of, then you are really following the Service Locator pattern.
To some extent you're right. Inversion of control does not need to mean using IoC container at all. If your object graph is small enough and convenient enough to be created at once in some kind of bootstrapping code, that's inversion of control, too.
But using an IoC tools simplifies the object creation in case of more complex scenarios. Using IoC tools you can manage object lifecycles, compose your object graph from different configurations or when not the whole graph is known at compile time, easily defer the object creation etc. etc.
There is no general solution. Everything depends from your specific needs. For a simple project with few classes, using IoC can be more annoying than helpful. For a big project I can't even imagine how the bootstrapping code need to look like.
See my post here for an extensive response to this question.
Most of the other answers here are correct, and say pretty much the same thing. I would add that most IoC containers allow you to auto-bind types to themselves, or use binding by convention. If you set up Unity to do that, then you can get rid of all that binding code entirely.
The difference is that you are doing the dependency injection instead of Unity doing dependency injection. In your example, you would have to know what types need to be created coupling your code to those types. You now need to know in your code that Impl1 should be created whenever you need a Type1.
Here's a simple code illustration of what other's have said (albeit taking a few liberties, property injection instead of constructor injection and assuming you've registered your types, etc).
public interface IFoo { }
public interface IBar { IFoo FooImpl { get; set; } }
public interface IBaz { IBar BarImpl { get; set; } }
public interface IBat { IBaz BazImpl { get; set; } }
As your object graph grows and dependencies are nested further and further down the graph, you'll have to provide the whole tree:
var bat = new Bat{
BazImpl = new BazImpl() {
BarImpl = new BarImpl() {
FooImpl = new FooImpl()
}
}
};
However, if you use the container correctly, all of that resolution comes based on what you've registered:
var bat = container.Resolve<IBat>()
Much like the other answers have probably stated, an IoC container is not required to perform dependency injection. It simply provides for automated dependency injection. If you don't get much of an advantage from the automation, then don't worry too much about a container, especially at the entry point of your application where you're injecting the initial objects.
There are however some things an IoC can make easier:
Lazy initialization. Autofac and a few others (not sure about Unity) can detect a constructor that takes a Func<IMyDependency> and, given a registration for an IDependency, will automatically generate the appropriate factory method. This reduces the front-loading often required in a DI system, where a lot of big objects like repositories have to be initialized and passed into the top-level object.
Sub-dependency hiding. Say class A needs to instantiate a class B, and B needs C, but A shouldn't know about C. Maybe even class Z which created A can't even know about C. This is the thing for which IoCs were created; throw A, B and C into the container, shake it up and resolve a fully-hydrated B to give to A, or a factory method which can be injected into A (automatically) and which the A can use to create all the B references it wants.
Simple "singletoning". Instead of creating and using a static singleton, an IoC can be told to create and return one and only one instance of any registered dependency no matter how many times that dependency is asked for. This allows the developer to turn any ordinary instance class into a singleton for use in the container, with no code change to the class itself required.
Your example is very simple, and the object graph would be very easily managable without using a DI framework. If this is really the extent of what is needed, doing manual DI would work fine.
The value of using a DI framework goes up very quickly as the dependency graph becomes more complex.

Dependency Injection vs Service Location

I am currently weighing up the advantages and disadvantages between DI and SL. However, I have found myself in the following catch 22 which implies that I should just use SL for everything, and only inject an IoC container into each class.
DI Catch 22:
Some dependencies, like Log4Net, simply do not suit DI. I call these meta-dependencies and feel they should be opaque to calling code. My justification being that if a simple class 'D' was originally implemented without logging, and then grows to require logging, then dependent classes 'A', 'B', and 'C' must now somehow obtain this dependency and pass it down from 'A' to 'D' (assuming 'A' composes 'B', 'B' composes 'C', and so on). We have now made significant code changes just because we require logging in one class.
We therefore require an opaque mechanism for obtaining meta-dependencies. Two come to mind: Singleton and SL. The former has known limitations, primarily with regards to rigid scoping capabilities: at best a Singleton will use an Abstract Factory which is stored at application scope (ie. in a static variable). This allows some flexibility, but is not perfect.
A better solution would be to inject an IoC container into such classes, and then use SL from within that class to resolve these meta-dependencies from the container.
Hence catch 22: because the class is now being injected with an IoC container, then why not use it to resolve all other dependencies too?
I would greatly appreciate your thoughts :)
Because the class is now being injected with an IoC container, then why not use it to resolve all other dependencies too?
Using the service locator pattern completely defeats one of the main points of dependency injection. The point of dependency injection is to make dependencies explicit. Once you hide those dependencies by not making them explicit parameters in a constructor, you're no longer doing full-fledged dependency injection.
These are all constructors for a class named Foo (set to the theme of the Johnny Cash song):
Wrong:
public Foo() {
this.bar = new Bar();
}
Wrong:
public Foo() {
this.bar = ServiceLocator.Resolve<Bar>();
}
Wrong:
public Foo(ServiceLocator locator) {
this.bar = locator.Resolve<Bar>();
}
Right:
public Foo(Bar bar) {
this.bar = bar;
}
Only the latter makes the dependency on Bar explicit.
As for logging, there's a right way to do it without it permeating into your domain code (it shouldn't but if it does then you use dependency injection period). Amazingly, IoC containers can help with this issue. Start here.
Service Locator is an anti-pattern, for reasons excellently described at http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. In terms of logging, you could either treat that as a dependency just like any other, and inject an abstraction via constructor or property injection.
The only difference with log4net, is that it requires the type of the caller that uses the service. Using Ninject (or some other container) How can I find out the type that is requesting the service? describes how you can solve this (it uses Ninject, but is applicable to any IoC container).
Alternatively, you could think of logging as a cross cutting concern, which isn't appropriate to mix with your business logic code, in which case you can use interception which is provided by many IoC containers. http://msdn.microsoft.com/en-us/library/ff647107.aspx describes using interception with Unity.
My opinion is that it depends. Sometimes one is better and sometimes another. But I'd say that generaly I prefer DI. There are few reasons for that.
When dependency is injected somehow into component it can be treated as part of its interface. Thus its easier for component's user to supply this dependecies, cause they are visible. In case of injected SL or Static SL that dependencies are hidden and usage of component is a bit harder.
Injected dependecies are better for unit testing cause you can simply mock them. In case of SL you have to setup Locator + mock dependencies again. So it is more work.
Sometimes logging can be implemented using AOP, so that it doesn't mix with business logic.
Otherwise, options are :
use an optional dependency (such as setter property), and for unit test you don't inject any logger. IOC container will takes care of setting it automatically for you if you run in production.
When you have a dependency that almost every object of your app is using ("logger" object being the most commmon example), it's one of the few cases where the singleton anti-pattern becomes a good practice. Some people call these "good singletons" an Ambient Context:
http://aabs.wordpress.com/2007/12/31/the-ambient-context-design-pattern-in-net/
Of course this context has to be configurable, so that you can use stub/mock for unit testing.
Another suggested use of AmbientContext, is to put the current Date/Time provider there , so that you can stub it during unit test, and accelerates time if you want.
This is regarding the 'Service Locator is an Anti-Pattern' by Mark Seeman.
I might be wrong here. But I just thought I should share my thoughts too.
public class OrderProcessor : IOrderProcessor
{
public void Process(Order order)
{
var validator = Locator.Resolve<IOrderValidator>();
if (validator.Validate(order))
{
var shipper = Locator.Resolve<IOrderShipper>();
shipper.Ship(order);
}
}
}
The Process() method for OrderProcessor does not actually follow the 'Inversion of Control' principle. It also breaks the Single Responsibility principle at the method level. Why should a method be concerned with instantiating the
objects(via new or any S.L. class) it needs to accomplish anything.
Instead of having the Process() method create the objects the constructor can actually have the parameters for the respective objects(read dependencies) as shown below. Then HOW can a Service Locator be any different from a IOC
container. AND it will aid in Unit Testing as well.
public class OrderProcessor : IOrderProcessor
{
public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
{
this.validator = validator;
this.shipper = shipper;
}
public void Process(Order order)
{
if (this.validator.Validate(order))
{
shipper.Ship(order);
}
}
}
//Caller
public static void main() //this can be a unit test code too.
{
var validator = Locator.Resolve<IOrderValidator>(); // similar to a IOC container
var shipper = Locator.Resolve<IOrderShipper>();
var orderProcessor = new OrderProcessor(validator, shipper);
orderProcessor.Process(order);
}
I have used the Google Guice DI framework in Java, and discovered that it does much more than make testing easier. For example, I needed a separate log per application (not class), with the further requirement that all my common library code use the logger in the current call context. Injecting the logger made this possible. Admittedly, all the library code needed to be changed: the logger was injected in the constructors. At first, I resisted this approach because of all the coding changes required; eventually I realized that the changes had many benefits:
The code became simpler
The code became much more robust
The dependencies of a class became obvious
If there were many dependencies, it was a clear indication that a class needed refactoring
Static singletons were eliminated
The need for session or context objects disappeared
Multi-threading became much easier, because the DI container could be built to contain just one thread, thus eliminating inadvertent cross-contamination
Needless to say, I am now a big fan of DI, and use it for all but the most trivial applications.
We've landed on a compromise: use DI but bundle top-level dependencies into an object avoiding refactoring hell should those dependencies change.
In the example below, we can add to 'ServiceDependencies' without having to refactor all derived dependencies.
Example:
public ServiceDependencies{
public ILogger Logger{get; private set;}
public ServiceDependencies(ILogger logger){
this.Logger = logger;
}
}
public abstract class BaseService{
public ILogger Logger{get; private set;}
public BaseService(ServiceDependencies dependencies){
this.Logger = dependencies.Logger; //don't expose 'dependencies'
}
}
public class DerivedService(ServiceDependencies dependencies,
ISomeOtherDependencyOnlyUsedByThisService additionalDependency)
: base(dependencies){
//set local dependencies here.
}
I know that people are really saying DI is the only good IOC pattern but I don't get this. I will try to sell SL a bit. I will use the new MVC Core framework to show you what I mean. First DI engines are really complex. What people really mean when they say DI, is use some framework like Unity, Ninject, Autofac... that do all the heavy lifting for you, where SL can be as simple as making a factory class. For a small fast project this is an easy way to do IOC without learning a whole framework for proper DI, they might not be that difficult to learn but still.
Now to the problem that DI can become. I will use a quote from MVC Core docs.
"ASP.NET Core is designed from the ground up to support and leverage dependency injection." Most people say that about DI "99% of your code base should have no knowledge of your IoC container." So why would they need to design from ground up if only 1% of code should be aware of it, didn't old MVC support DI? Well this is the big problem of DI it depends on DI. Making everything work "AS IT SHOULD BE DONE" takes a lot of work. If you look at the new Action Injection is this not depending on DI if you use [FromServices] attribute. Now DI people will say NO you are suppose to go with Factories not this stuff, but as you can see not even people making MVC did it right. The problem of DI is visible in Filters as well look at what you need to do to get DI in a filter
public class SampleActionFilterAttribute : TypeFilterAttribute
{
public SampleActionFilterAttribute():base(typeof(SampleActionFilterImpl))
{
}
private class SampleActionFilterImpl : IActionFilter
{
private readonly ILogger _logger;
public SampleActionFilterImpl(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation("Business action starting...");
// perform some business logic work
}
public void OnActionExecuted(ActionExecutedContext context)
{
// perform some business logic work
_logger.LogInformation("Business action completed.");
}
}
}
Where if you used SL you could have done this with var _logger = Locator.Get();. And then we come to the Views. With all there good will regarding DI they had to use SL for the views. the new syntax #inject StatisticsService StatsService is the same as var StatsService = Locator.Get<StatisticsService>();.
The most advertised part of DI is unit testing. But what people and up doing is just testing there mock services with no purpose or having to wire up there DI engine to do real tests. And I know that you can do anything badly but people end up making a SL locator even if they don't know what it is. Where not a lot of people make DI without ever reading on it first.
My biggest problem with DI is that the user of the class must be aware of the inner workings of the class in other to use it.
SL can be used in a good way and has some advantages most of all its simplicity.
I know this question is a little old, I just thought I would give my input.
In reality, 9 times out of 10 you really don't need SL and should rely on DI. However, there are some cases where you should use SL. One area that I find myself using SL (or a variation, thereof) is in game development.
Another advantage of SL (in my opinion) is the ability to pass around internal classes.
Below is an example:
internal sealed class SomeClass : ISomeClass
{
internal SomeClass()
{
// Add the service to the locator
ServiceLocator.Instance.AddService<ISomeClass>(this);
}
// Maybe remove of service within finalizer or dispose method if needed.
internal void SomeMethod()
{
Console.WriteLine("The user of my library doesn't know I'm doing this, let's keep it a secret");
}
}
public sealed class SomeOtherClass
{
private ISomeClass someClass;
public SomeOtherClass()
{
// Get the service and call a method
someClass = ServiceLocator.Instance.GetService<ISomeClass>();
someClass.SomeMethod();
}
}
As you can see, the user of the library has no idea this method was called, because we didn't DI, not that we'd be able to anyways.
If the example only takes log4net as dependency, then you only need to do this:
ILog log = LogManager.GetLogger(typeof(Foo));
There is no point to inject the dependency as log4net provides granular logging by taking the type (or a string) as parameter.
Also, DI is not correlated with SL. IMHO the purpose of ServiceLocator is for resolve optional dependencies.
Eg: If the SL provides an ILog interface, i will write logging daa.
For DI, do you need to have a hard reference to the injected type assembly? I don’t see anyone talking about that. For SL, I can tell my resolver where to load my type dynamically when it needed from a config.json or similar. Also, if your assembly contains several thousand types and their inheritance, do you need thousands cascading call to the service collection provider to register them? That’s where I do see much talk about. Most are talking about the benefit of DI and what it is in general, when it comes to how to implement it in .net, they presented with an extension method for adding reference to a hard linked types assembly. That’s not very decoupling to me.

Categories

Resources