Confusion about DI, IoC and service locators - c#

I have read various articles about IoC, DIP, DI and Service Locators but I'm a bit confused which is which because some articles have too vague examples and some other articles have just some specific examples without mentioning other cases.
Could you please clear this up for me, looking at the examples below and shortly explaining which examples match which pattern?
manually passing interface to constructor:
class Consumer
{
public Consumer(IStore store){...}
}
...
Consumer c = new Consumer(new ConcreteStore());
the same as the first example but using some 3rd party library (Unity, Windsor, Ninject)
the same as the first example but using BaseStore class instead of IStore interface
passing dependency to some other method, not to constructor:
class Consumer
{
public BySomething(IStore store){...}
}
...
Consumer c = new Consumer();
c.BySomething(new ConcreteStore());
passing dependencies masked inside of some other interface (bonus for this solution - when some other things are invented in the "world" and Consumer wishes to use them, we don't have to change constructor argument but just update IWorld; and we can completely replace entire World with something else when testing):
interface IWorld
{
IDictionary<string,IStore> Stores { get; set; }
IDictionary<string,ICityMap> Maps { get; set; }
...
}
class Consumer
{
public Consumer(IWorld world){...}
public BySomething(string store, string city){...}
}
...
IWorld myWorld = new HeavenlyWorld();
... // adding stores, maps and whatnot
Consumer c = new Consumer(myWorld);
a sub-question: in this case, is IWorld a service locator or not exactly?
passing a call-back function or delegate (.NET Action in this case):
c.BySomething(store, city, new Action(() => {...} ));
I added this case because the article Inversion of Control states that every callback is IoC. Is it true?

Everything you listed is a form of Dependency Injection.
"Poor Man's" DI
DI using an IoC container
"Poor Man's" DI again. DI works whether you are using an interface or an abstract class.
Method Injection
I'm not sure what you're asking here. It sounds like you want to change the instance of IWorld at runtime, which might be a case for Property Injection instead of Constructor Injection. Properties are oft used for optional dependencies or those that can change. Whether you then set that dependency at run-time with a Service Locator or other means is up to you. Another thing to consider is that IWorld might just depend on context, in which case you could do a context-depdendent constructor injection, the details of which are beyond the scope of this question.
Not related to DI

Every time you pass a dependency as a constructor/method argument, that's Dependecy Injection. It can be manual, like in most of your examples, or automatic using a DI Container aka IoC Container.
Using a container means the objects using deps are constructed by the container. You could ask the container directly for that service and in that case, there's a static property or method ( think DependecyResolver in asp.net mvc) that exposes that service. In that case you're using the Service Locator pattern. IWork in your example is not a locator, it's just a dependency.
To continue with the dependency resolver example, you register all relevant types into a container, the container is build then registered as the dependency resolver. The asp.net mvc framwork then uses the resolver (the Service Locator - SL) to instantiate controllers, views and all the deps these require.
To use the SL pattern is ok as part of a framework, but it's not ok if you're using it in your app to instantiate objects, because it couples the code to the locator. Sometimes is the only solution but 99% you is just an anti-pattern.

Related

Dependency injection of multiple instances of same type in ASP.NET Core 2

In ASP.NET Core 2 Web Api, I want to use dependency injection to inject httpClientA instance of HttpClient to ControllerA, and an instance httpClientB of the HttpClient to ControllerB.
The DI registration code would look something like:
HttpClient httpClientA = new HttpClient();
httpClientA.BaseAddress = endPointA;
services.AddSingleton<HttpClient>(httpClientA);
HttpClient httpClientB = new HttpClient();
httpClientB.BaseAddress = endPointB;
services.AddSingleton<HttpClient>(httpClientB);
I know I could subclass HttpClient to make a unique type for each controller, but that doesn't scale very well.
What is a better way?
UPDATE
Specifically regarding HttpClient Microsoft seems to have something in the works
https://github.com/aspnet/HttpClientFactory/blob/dev/samples/HttpClientFactorySample/Program.cs#L32 - thanks to #mountain-traveller (Dylan) for pointing this out.
Note: This answer uses HttpClient and a HttpClientFactory as an example but easily applies to any other kind of thing. For HttpClient in particular, using the new IHttpClientFactory from Microsoft.Extensions.Http is preferred.
The built-in dependency injection container does not support named dependency registrations, and there are no plans to add this at the moment.
One reason for this is that with dependency injection, there is no type-safe way to specify which kind of named instance you would want. You could surely use something like parameter attributes for constructors (or attributes on properties for property injection) but that would be a different kind of complexity that likely wouldn’t be worth it; and it certainly wouldn’t be backed by the type system, which is an important part of how dependency injection works.
In general, named dependencies are a sign that you are not designing your dependencies properly. If you have two different dependencies of the same type, then this should mean that they may be interchangeably used. If that’s not the case and one of them is valid where the other is not, then that’s a sign that you may be violating the Liskov substitution principle.
Furthermore, if you look at those dependency injection containers that do support named dependencies, you will notice that the only way to retrieve those dependencies is not using dependency injection but the service locator pattern instead which is the exact opposite of inversion of control that DI facilitates.
Simple Injector, one of the larger dependency injection containers, explains their absence of named dependencies like this:
Resolving instances by a key is a feature that is deliberately left out of Simple Injector, because it invariably leads to a design where the application tends to have numerous dependencies on the DI container itself. To resolve a keyed instance you will likely need to call directly into the Container instance and this leads to the Service Locator anti-pattern.
This doesn’t mean that resolving instances by a key is never useful. Resolving instances by a key is normally a job for a specific factory rather than the Container. This approach makes the design much cleaner, saves you from having to take numerous dependencies on the DI library and enables many scenarios that the DI container authors simply didn’t consider.
With all that being said, sometimes you really want something like this and having a numerous number of subtypes and separate registrations is simply not feasible. In that case, there are proper ways to approach this though.
There is one particular situation I can think of where ASP.NET Core has something similar to this in its framework code: Named configuration options for the authentication framework. Let me attempt to explain the concept quickly (bear with me):
The authentication stack in ASP.NET Core supports registering multiple authentication providers of the same type, for example you might end up having multiple OpenID Connect providers that your application may use. But although they all share the same technical implementation of the protocol, there needs to be a way for them to work independently and to configure the instances individually.
This is solved by giving each “authentication scheme” a unique name. When you add a scheme, you basically register a new name and tell the registration which handler type it should use. In addition, you configure each scheme using IConfigureNamedOptions<T> which, when you implement it, basically gets passed an unconfigured options object that then gets configured—if the name matches. So for each authentication type T, there will eventually be multiple registrations for IConfigureNamedOptions<T> that may configure an individual options object for a scheme.
At some point, an authentication handler for a specific scheme runs and needs the actual configured options object. For this, it depends on IOptionsFactory<T> whose default implementation gives you the ability to create a concrete options object that then gets configured by all those IConfigureNamedOptions<T> handlers.
And that exact logic of the options factory is what you can utilize to achieve a kind of “named dependency”. Translated into your particular example, that could for example look like this:
// container type to hold the client and give it a name
public class NamedHttpClient
{
public string Name { get; private set; }
public HttpClient Client { get; private set; }
public NamedHttpClient (string name, HttpClient client)
{
Name = name;
Client = client;
}
}
// factory to retrieve the named clients
public class HttpClientFactory
{
private readonly IDictionary<string, HttpClient> _clients;
public HttpClientFactory(IEnumerable<NamedHttpClient> clients)
{
_clients = clients.ToDictionary(n => n.Name, n => n.Client);
}
public HttpClient GetClient(string name)
{
if (_clients.TryGet(name, out var client))
return client;
// handle error
throw new ArgumentException(nameof(name));
}
}
// register those named clients
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("A", httpClientA));
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("B", httpClientB));
You would then inject the HttpClientFactory somewhere and use its GetClient method to retrieve a named client.
Obviously, if you think about this implementation and about what I wrote earlier, then this will look very similar to a service locator pattern. And in a way, it really is one in this case, albeit built on top of the existing dependency injection container. Does this make it better? Probably not, but it’s a way to implement your requirement with the existing container, so that’s what counts. For full defense btw., in the authentication options case above, the options factory is a real factory, so it constructs actual objects and doesn’t use existing pre-registered instances, so it’s technically not a service location pattern there.
Obviously, the other alternative is to completely ignore what I wrote above and use a different dependency injection container with ASP.NET Core. For example, Autofac supports named dependencies and it can easily replace the default container for ASP.NET Core.
Another option is to
use an additional generic type parameter on the interface or a new interface implementing the non generic interface,
implement an adapter/interceptor class to add the marker type and then
use the generic type as “name”
I’ve written an article with more details: Dependency Injection in .NET: A way to work around missing named registrations
Use named registrations
This is exactly what named registrations are for.
Register like this:
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientA");
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientB");
And retrieve this way:
var clientA = container.Resolve<HttpClient>("ClientA");
var clientB = container.Resolve<HttpClient>("ClientB");
If you want ClientA or ClientB automatically injected into another registered type, see this question. Example:
container.RegisterType<ControllerA, ControllerA>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientA") // Resolve parameter of type HttpClient using name "ClientA"
)
);
container.RegisterType<ControllerB, ControllerB>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientB") // Resolve parameter of type HttpClient using name "ClientB"
)
);
Use a factory
If your IoC container lacks any ability to handle named registrations, you could inject a factory and let the controller decide how to get the instance. Here is a really simple example:
class HttpClientFactory : IHttpClientFactory
{
private readonly Dictionary<string, HttpClient> _clients;
public void Register(string name, HttpClient client)
{
_clients[name] = client;
}
public HttpClient Resolve(string name)
{
return _clients[name];
}
}
And in your controllers:
class ControllerA
{
private readonly HttpClient _httpClient;
public ControllerA(IHttpClientFactory factory)
{
_httpClient = factory.Resolve("ClientA");
}
}
And in your composition root:
var factory = new HttpClientFactory();
factory.Register("ClientA", new HttpClient());
factory.Register("ClientB", new HttpClient());
container.AddSingleton<IHttpClientFactory>(factory);
Really the consumer of the service should not care where about the implementation of the instance it is using. In your case I see no reason to manually register many different instances of HttpClient. You could register the type once and any consuming instance that needs an instance will get it's own instance of HttpClient. You can do that with AddTransient.
The AddTransient method is used to map abstract types to concrete services that are instantiated separately for every object that requires it
services.AddTransient<HttpClient, HttpClient>();

theory: "Service Locator" "IOC Container" "IOC" "DI"

can you help me with theory of some patterns. I have tried to describe them, I have tried my best, but I think my statements are wrong, so help )).
1) "DI" and "IOC" - the same.
2) "IOC Container" - it is an instance of an object that can resolve dependences like:
void Test()
{
// create IOC Container to resolve
// dependences for SomeMethod method
var container = new SomeContainer();
container.For(typeof(IEmaleSender), typeof(SuperEmaleSender));
// Pass IOC Container to resolve dependences in SomeMethod
SomeMethod(container);
}
void SomeMethod(SomeContainer container)
{
IEmaleSender emailSender = container.Resolve(IEmaleSender);
emailSender.SendEmail();
}
3) "Service Locator" - It is something like static object that contains Dictionary<Type, object> where value is an instance of key type. And this static object have 2 methods: Add and Get. So I can add object on start of my application and request it from everywhere:
void Test()
{
// Assign instanse of SuperEmaleSender to Locator
SuperEmaleSender emailSender = new SuperEmaleSender()
SomeLocator.Add(typeof(SuperEmaleSender), emailSender);
SomeMethod();
}
void SomeMethod()
{
SuperEmaleSender emailSender = SomeLocator.Get(typeof(SuperEmaleSender));
emailSender.SendEmail();
}
4) It is a good practice to combine "Service Locator" and "IOC Container". So you can instantiate "IOC Container" on application start and request it through "Service Locator" from everywhere.
5) In ASP MVC5, "Service Locator" already included. I'm talking about DependencyResolver.
Thank you for your help.
As for the combining service locator with IoC - when you have proper IoC container, you really shouldn't use service locator (or perhaps in most cases you should not use it at all), because the whole point of IoC and DI is to pass dependencies from outside of class and specify explicitely what dependecies this class has. Using service locator inside would hide the dependency. Service locator is by some people considered an anti-pattern.
Service Locator is ALMOST an extremely primitive Dependency Injection. It generally only lets you return singleton instances. Its not really DI because you have to get instances by hand and new up objects by hand rather then let the DI engine do it for you (new up object and inject the service references into them). DI also gives you more control over the lifetime of the objects.
DI stands for Depency Injection and IoC for Inversion of Control.
Imagine you have a class that access the database. The responsability of that class is to insert an item, but you need a database connection to do so. If the responsability of the class is only to insert an item, it won't know how to start that connection, only how to use it. Thinking of it, you'll set the connection as a dependency of that class, passing the responsability of creating that connection to anyone that want to use it. You are inverting the control using dependency injection, passing the responsability to anyone that knows how a connection works.
You can use an IoC container to help you manage the dependencies between your classes.
You can see this question for a more detailed answer: Inversion of Control vs Dependency Injection

Replacing ServiceLocator with DependencyInjection when implementing modal dialogs in MVVM WPF application

I am writing my first WPF application and I would like to ask you for help with a problem that I encountered.
I am trying to follow the MVVM pattern and I came to a point where I need to implement modal dialogs. I googled/read on the topic for some time and I was able to settle on a solution. However, when refactoring I encountered a dilemma that concerns using a DI (constructor injection) as a replacement of a service locator.
I am going to be referencing these: http://pastebin.com/S6xNjtWW.
I really like the approach of Roboblob:
First: He creates an abstraction of a modal dialog (interface). I named the interface IModalDialog and this is how it looks like:
public interface IModalDialog
{
bool? DialogResult { get; set; }
object DataContext { get; set; }
void Show();
bool? ShowDialog();
void Close();
event EventHandler Closed;
}
Second: An abstraction of modal dialog service:
public interface IModalDialogService
{
void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose) where TDialogViewModel : class;
void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel) where TDialogViewModel : class;
}
Third: The concrete implementation of IModalDialogService:
public class ModalDialogService : IModalDialogService
{
public void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose) where TDialogViewModel : class
{
// set datacontext
if (viewModel != null)
{
view.DataContext = viewModel;
}
((System.Windows.Window)view).Owner = System.Windows.Application.Current.MainWindow;
// register
if (onDialogClose != null)
{
view.Closed += (sender, e) => onDialogClose(viewModel);
}
view.ShowDialog();
}
public void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel) where TDialogViewModel : class
{
this.ShowDialog(view, viewModel, null);
}
Fourth: There are more implementations of IModalDialog. Each is a Window-derived class that implements IModalDialog.
Before I ask the question (describe the problem), I need to explain this beforehand:
Let's say that I have some more services, like for example IMessageBoxService.
Then I need to declare these dependencies in the constructor of MainWindowViewModel:
public MainWindowViewModel(IModalDialogService a,
IMessageBoxService b,
...)
so that I can inject them (either by hand or using IOC container like Unity, etc.).
In order to be able to use the modal dialog service there is one missing piece of puzzle - the ability to resolve a concrete implementation of IModalDialog based on some key.
Roboblob in his article solves this last piece of puzzle using a ServiceLocator pattern:
public class Bootstrapper
{
public static void InitializeIoc()
{
SimpleServiceLocator.SetServiceLocatorProvider(new UnityServiceLocator());
SimpleServiceLocator.Instance.Register<IModalDialogService, ModalDialogService>();
SimpleServiceLocator.Instance.Register<IMessageBoxService, MessageBoxService>();
...
SimpleServiceLocator.Instance.Register<IModalWindow, EditUserModalDialogView>(Constants.EditUserModalDialog);
}
}
so he inside his MainWindowViewModel simply calls the static classes Get and resolves a concrete implementation of IModalDialog window based on a key.
Even Josh Smith uses a similar approach in his article but in comments he says that (DI - constructor injection) is a valid option.
The referenced StackOverflow answer also describes a similar WindowViewLoaderService that could be modified and use.
So the question is - what would be the best way to replace the ServiceLocator (which resolves the concrete implementations of IModalDialog) with a dependency injection?
My train of thoughts was:
One possibility is (due to the project not being very big/developed by me only) to just create a new service (e.g. called IModalDialogResolver) that would create and return new instances of concrete implementations of IModalDialog. Have all the services injected by hand.
Then I thought about an IOC container (Unity). I have no experience with it. I thought that maybe I don't have to write the IModalDialogResolver as I could register the different implementations of IModalDialog with Unity container => but then how do I use the container inside MainWindowViewModel? I cannot pass the reference to the constructor as that would be a step back to ServiceLocation.
So then I thought that maybe I can use one unity container in the bootstrapper to resolve all the services and use another one internally inside the IModalDialogResolver. But I don't know whether this is a good idea regarding the recommended usage of Unity. I really know too little to judge this. But something tells me that this is not a good idea as it creates a hidden dependency on the container + if the container is a singleton that would be equivalent to just passing the reference into the constructor.
To maybe better explain the mental block that I have: I would like to use an IOC container (e.g. Unity) to have the interfaces constructed and injected by it. But then I cannot just put IModalDialog as a parameter inside a constructor. So probably I really need to wrap this inside a service and implement myself - but then (provided that Unity can do this out of the box) it doesn't make sense to have Unity there in the first place if i cannot use it.
I know one of the alternatives is to put this one service into a base class, but for the sake of argument, let's not consider this. I really would like to learn about the right way to have this solved using dependency injection.
It's perfectly valid and expected for you to access the IoC container within your composition root.
In fact this should be the only location where you container is accessed.
In the example you've given, that's all that is happening - the concrete implementations are being registered in the container within the composition root.
So to answer your question, you don't need to replace the use of the service locator pattern here, as it's just a mechanism for registering the types in the composition root, which is perfectly valid.
If you wish to instantiate the modal dialog service based on some run time conditions, then you should inject a model dialog service factory instead (again an abstraction with an implementation registered in your container), and then the factory would have a method to create the model dialog service and this factory method would take the run time parameters required.
Your factory could then new up the appropriate model dialog service appropriately based on the run time parameters. Alternatively, it could also resolve the appropriate model dialog service from the container, which would obviously require the factory to have a reference to the container.
Most containers support automated factory types, so that you only need to define the interface for the factory, and the container will automatically implement the factory using conventions. Castle.Windsor for example has the Typed Factory Facility and Unity has some equivalents.

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