Dependency Injection in Akka .NET with state constructor parameters - c#

Having something like a string parameter in a constructor makes dependency injection very messy. Think:
public class CurrencyActor
{
public CurrencyActor(string currency, IRepository repository)
{
...
There have been other questions (such as this one) to address this particular problem with dependency injection. Often this is solved by rethinking the design and refactoring.
However, what if it actually makes sense to have multiple versions of an object that are each responsible for different data (e.g. a CurrencyActor for each currency)? This is pretty normal when using an actor model such as Akka .NET, but makes sense even outside that domain.
What is the best way to create these multiple instances using dependency injection while passing in the initial state they need?

Having a dependency in a constructor is not messy, it's very very common. There is nothing wrong with this.
You could create a default props static method on the CurrencyActor that takes in your dependencies:
public static Props CreateProps(string currency, Irepository repo)
{
return Props.Create(() => new CurrrncyActor(currency, repo));
}
Then create as many as you like:
var usCurrency = system.ActorOf(CurrencyActor.CreateProps("US", someRepo), "US");
var swedishCurrency = system.ActorOf(CurrencyActor.CreateProps("SEK", someRepo), "SEK");
[Update]
Regarding the use of DI containers with Akka, this was listed as no. 2 out of the top 7 mistakes people make when using akka.net
https://petabridge.com/blog/top-7-akkadotnet-stumbling-blocks/
Thus it’s considered to be a good practice for actors to manage their own dependencies, rather than delegate that work to a DI framework.
So basically don't do it. And if you must, according to that article, Autofac is the best choice
[Update 2]
If you want to dynamically create new instances of the same Actor but change some initial state, then you could have a Supervisor that is responsible for creating them:
public class MatchesSupervisor : ReceiveActor
{
List<IActorRef> _matches = new List<IActorRef>();
public void MatchesSupervisor()
{
Receive<SomeCommandToStartANewMatch>(msg =>
{
// store the currently active matches somewhere, maybe on a FullTime message they would get removed?
_matches.Add(Context.ActorOf(MatchActor.Create(msg.SomeMatchId)));
}
}
}
In the above example, there is no DI container being used, and if each MatchActor needed something else, like an IRepository, then this would be passed into the MatchesSupervisor when it is created, and subsequently passed to each MatchActor when they are created.
It also kinda depends where the state is coming from, and what the mechanism is for starting a new Match - i've just presumed some other Actor is sending a message.
(I'm typing on an ipad so the above code might not actually compile but hopefully you get the idea, i also left out an implementation of MatchActor, but it would just be an Actor that gets some values passed into its constructor)
Hope this helps!

Related

What is the point of dependency injection container? [duplicate]

This question already has answers here:
What is the difference between an interface and a class, and why I should use an interface when I can implement the methods directly in the class?
(16 answers)
Closed 5 years ago.
With .net core you can register "Services" which as I understand, simply means you can register types to concrete classes.
As such, I decided it's about time I learnt DI and practised it. I understand the concept, and with testing it is massively beneficial. However what confuses me is the idea of registering services and whether it's actually needed.
For example, if I have:
public class MyClass
{
public MyClass(IDataContext)
{
... store it
}
}
Then this means I can inject any class that implements the IDataContext, allowing for fakes and moqs in testing. But why would I register a service and map IDataContext to a concrete class in the startup? Is there something wrong with just using the following in other methods:
DataContext dc = new DataContext(); // concrete
var c = new MyClass(dc);
Edit
This question was around the point of using the container (services) rather than why use an interface in the constructor.
Now those classes where you put this code
public class MyService
{
public void DoSomething()
{
DataContext dc = new DataContext(); // concrete
var c = new MyClass(dc);
c.DoSomething();
}
}
have a hard dependency on DataContext and MyClass. So you can't test MyService in isolation. Classes shouldn't care how other classes do what they do, they should only care that they do what they say they're going to do. That's why we use interfaces. This is separation of concerns. Once you've achieved this, you can unit test any piece of code in isolation without depending on the behavior of outside code.
Registering your dependencies up front in one location is also cleaner and means you can swap dependencies out by changing one location instead of hunting down all the usages and changing them individually.
In my code example at the top, MyService requires the usage of both DataContext and MyClass. Instead, it should be like this:
public class MyService
{
private readonly IMyClass _myClass;
public MyService(IMyClass myClass)
{
_myClass = myClass;
}
public void DoSomething()
{
_myClass.DoSomething();
}
}
public interface IMyClass
{
void DoSomething();
}
public class MyClass : IMyClass
{
private readonly IDataContext _context;
public MyClass(IDataContext context)
{
_context = context;
}
public void DoSomething()
{
_context.SaveSomeData();
}
}
Now MyService isn't dependent on DataContext at all, it doesn't need to worry about it because that's not its job. But it does need something that fulfills IMyClass, but it doesn't care how it's implemented. MyService.DoSomething() can now be unit tested without depending on the behavior of other code.
If you weren't using a container to handle satisfying the dependencies, then you're probably introducing hard dependencies into your classes, which defeats the entire point of coding against an interface in the first place.
Testing in isolation is important. It's not a unit test if you're testing more than one finite piece of code. It's an integration test (which have their own value for different reasons). Unit tests make it quick and easy to verify a finite block of code works as expected. When a unit test isn't passing, you know right where the problem is and don't have to search hard to find it. So if a unit test depends on other types, or even other systems (likely in this case, DataContext is specific to a particular database) then we can't test MyService without touching a database. And that means the database must be in a particular state for testing, which means the test likely isn't idempotent (you can't run it over and over and expect the same results.)
For more information, I suggest you watch Deep Dive into Dependency Injection and Writing Decoupled Quality Code and Testable Software by Miguel Castro. The best point he makes is that if you have to use new to create an instance of an object, you've tightly coupled things. Avoid using new, and Dependency Injection is a pattern that enables you to avoid it. (using new isn't always bad, I'm comfortable with using new for POCO models).
You can inject your dependencies manually. However this can get a very tedious task. If your services get bigger, you will get more dependencies, where each dependency on its own can have multiple dependencies.
If you change your dependencies, you need to adjust all usages. One of the main advantages of a DI container is, that the container will do all dependency resolving. No manual work required. Just register the service and use it wherever you want and how often you want.
For small projects this seems like too much overhead, but if your project grows a little, you will really appreciate this.
For fixed dependencies, which are strongly related and not likely to change, injecting them manually is fine.
Using a DI container has another advantage. The DI container will control the life cycle of its services. A service could be a singleton, transient (each request will get a new instance) or have scoped life time.
For example, if you have a transactional workflow. The scope could match the transaction. While in the transaction, requests to a service will return the same instance.
The next transaction will open a new scope and therefore will get new instances.
This allows you to either discard or commit all instances of one transaction, but prevents that following transaction uses resources from the previous one.
You right, you can create all instances manually. In small projects it's an usual practice. The place in your project where links the classes is called Composition Root, and what you do is Constructor Injection.
IoC-libraries can simplify this code, especially considering complex cases like life-time scopes and group registration.
Inversion of control (of constructing an object)
The idea of this pattern is when you want to construct an object you only need to know about the type of the object and nothing about its dependencies or parameters.
Dependency injection
This pattern is taking the inversion of control pattern a step further by enabling you to directly inject an object into a constructor for example.
Again you only need to know the type of the object you want to get and the dependency container will inject an object.
You also don't need to know if a new object is constucted or if you get a allready existing reference.
The most common used type of dependency injection is constructor injection but you could inject your type into other places like methods.
Seperation of concerns
Generally you register a type by an interface to get rid of the dependency on the type.
This is very helpfull for mocking types when testing and it helps to use the open closed principle.
Martin Fowler on "Inversion of Control Containers and the Dependency Injection pattern".

Dependency Injection With Unity Using Constructors With Runtime Parameters

I have the basics down of dependency injection but where I'm struggling is trying to put it together properly in an MVC API C# application using Unity. The issue I have is that I will have a controller that has a method, and in that method it will have say two objects. One of these objects will have a dependency on a data access layer and the other doesn't. I'm not quite sure on exactly how to set this up.
Lets say I have a controller with the following method that gets users from a search object. It also uses a SearchParameters object to perform the search. If you search with no name you get all results, or if you put a name you get any users with that name.
public Users[] GetUsers(string name) {
Company.SearchParameters searchParams = new Company.SearchParameters(name);
Company.UserSearchService searchService = new Company.UserSearchService(searchParams);
return searchService.Search();
}
This is of course a super simplified version but in this case UserSearchService in the Search method is doing an explicit database call. So I know that is a dependency I'd have to give it. SearchParameters really is just a class that holds data.
Here is where I'm not sure on exactly what to do next. The Controller itself doesn't have a dependency but since UserSearchService does I'm not sure how using unity I properly set that up and take into account runtime values for the constructor. I'm also not sure if SearchParameters is supposed to be considered a dependency or not.
Additionally SearchParameters and UserSearchService do not have any sort of backing interface if that matters and there are other methods on this controller that interact with other classes that have a similar need of a data access layer dependency such as perhaps Company.UserAccount.
The search parameters shouldn't be part of constructor; it should be part of the "Search" method. The SearchParameter object should not even be known outside of the UserSearchService class (Encapsulation). There should be some refactoring as neleus suggested. At the very least, to get things going, it should be refactored to something similar this:
public Users[] GetUsers(string name) {
// Or however you end up with your UserSearchService object.
// Ideally as an interface and an injected dependency...
Company.UserSearchService searchService = new Company.UserSearchService();
return searchService.Search(name);
}
Company.UserSearchService:
public Users[] Search(string name) {
// A factory would be a better option. This should also be an interface.
Company.SearchParameters searchParams = new Company.SearchParameters(name);
// Your logic here
}
I see here two tasks. The first is a refactoring where static dependencies have to be replaced with interfaces. The second task is to register your stuff in IoC container.
For the first task a minimum you need is to replace all references to Database in your UserSearchService with IDatabase interface (so that it can also be mocked) and allow it to be passed to constructor (constructor injection). To be able to provide an instance of IDatabase to the service you have to create the same dependency for the controller (again constructor injection). Then register the IDatabase implementation as shown in this post.
Update
I agree that dependency has to be removed from the controller. As you #Topojijo have suggested a factory for the UserSearchService can be used in this case. Guessing you have several cervices you need to make a factory for each and there may be an overhead if their count is large. In such case it's better to resolve the service directly from Unity container and move the searchParams to Search method:
public Users[] GetUsers(string name) {
Company.SearchParameters searchParams = new Company.SearchParameters(name);
Company.UserSearchService searchService = container.Resolve<Company.UserSearchService>();
return searchService.Search(searchParams);
}

Dependency Injection and the Strategy Pattern

There is an enormous amount of discussion on this topic, but everyone seems to miss an obvious answer. I'd like help vetting this "obvious" IOC container solution. The various conversations assume run-time selection of strategies and the use of an IOC container. I will continue with these assumptions.
I also want to add the assumption that it is not a single strategy that must be selected. Rather, I might need to retrieve an object-graph that has several strategies found throughout the nodes of the graph.
I will first quickly outline the two commonly proposed solutions, and then I will present the "obvious" alternative that I'd like to see an IOC container support. I will be using Unity as the example syntax, though my question is not specific to Unity.
Named Bindings
This approach requires that every new strategy has a binding manually added:
Container.RegisterType<IDataAccess, DefaultAccessor>();
Container.RegisterType<IDataAccess, AlphaAccessor>("Alpha");
Container.RegisterType<IDataAccess, BetaAccessor>("Beta");
...and then the correct strategy is explicitly requested:
var strategy = Container.Resolve<IDataAccess>("Alpha");
Pros: Simple, and supported by all IOC Containers
Cons:
Typically binds the caller to the IOC Container, and certainly requires the caller to know something about the strategy (such as the name "Alpha").
Every new strategy must be manually added to the list of bindings.
This approach is not suitable for handling multiple strategies in an object graph. In short, it does not meet requirements.
Abstract Factory
To illustrate this approach, assume the following classes:
public class DataAccessFactory{
public IDataAccess Create(string strategy){
return //insert appropriate creation logic here.
}
public IDataAccess Create(){
return //Choose strategy through ambient context, such as thread-local-storage.
}
}
public class Consumer
{
public Consumer(DataAccessFactory datafactory)
{
//variation #1. Not sufficient to meet requirements.
var myDataStrategy = datafactory.Create("Alpha");
//variation #2. This is sufficient for requirements.
var myDataStrategy = datafactory.Create();
}
}
The IOC Container then has the following binding:
Container.RegisterType<DataAccessFactory>();
Pros:
The IOC Container is hidden from consumers
The "ambient context" is closer to the desired result but...
Cons:
The constructors of each strategy might have different needs. But now the responsibility of constructor injection has been transferred to the abstract factory from the container. In other words, every time a new strategy is added it may be necessary to modify the corresponding abstract factory.
Heavy use of strategies means heavy amounts of creating abstract factories. It would be nice if the IOC container simply gave a little more help.
If this is a multi-threaded application and the "ambient context" is indeed provided by thread-local-storage, then by the time an object is using an injected abstract-factory to create the type it needs, it may be operating on a different thread which no longer has access to the necessary thread-local-storage value.
Type Switching / Dynamic Binding
This is the approach that I want to use instead of the above two approaches. It involves providing a delegate as part of the IOC container binding. Most all IOC Containers already have this ability, but this specific approach has an important subtle difference.
The syntax would be something like this:
Container.RegisterType(typeof(IDataAccess),
new InjectionStrategy((c) =>
{
//Access ambient context (perhaps thread-local-storage) to determine
//the type of the strategy...
Type selectedStrategy = ...;
return selectedStrategy;
})
);
Notice that the InjectionStrategy is not returning an instance of IDataAccess. Instead it is returning a type description that implements IDataAccess. The IOC Container would then perform the usual creation and "build up" of that type, which might include other strategies being selected.
This is in contrast to the standard type-to-delegate binding which, in the case of Unity, is coded like this:
Container.RegisterType(typeof(IDataAccess),
new InjectionFactory((c) =>
{
//Access ambient context (perhaps thread-local-storage) to determine
//the type of the strategy...
IDataAccess instanceOfSelectedStrategy = ...;
return instanceOfSelectedStrategy;
})
);
The above actually comes close to satisfying the overall need, but definitely falls short of the hypothetical Unity InjectionStrategy.
Focusing on the first sample (which used a hypothetical Unity InjectionStrategy):
Pros:
Hides the container
No need either to create endless abstract factories, or have consumers fiddle with them.
No need to manually adjust IOC container bindings whenever a new strategy is available.
Allows the container to retain lifetime management controls.
Supports a pure DI story, which means that a multi-threaded app can create the entire object-graph on a thread with the proper thread-local-storage settings.
Cons:
Because the Type returned by the strategy was not available when the initial IOC container bindings were created, it means there may be a tiny performance hit the first time that type is returned. In other words, the container must on-the-spot reflect the type to discover what constructors it has, so that it knows how to inject it. All subsequent occurrences of that type should be fast, because the container can cache the results it found from the first time. This is hardly a "con" worth mentioning, but I'm trying for full-disclosure.
???
Is there an existing IOC container that can behave this way? Anyone have a Unity custom injection class that achieves this effect?
As far as I can tell, this question is about run-time selection or mapping of one of several candidate Strategies.
There's no reason to rely on a DI Container to do this, as there are at least three ways to do this in a container-agnostic way:
Use a Metadata Role Hint
Use a Role Interface Role Hint
Use a Partial Type Name Role Hint
My personal preference is the Partial Type Name Role Hint.
I have achieved this requirement in many forms over the last couple of years. Firstly let's pull the main points I can see in your post
assume run-time selection of strategies and the use of an IOC container ... add the assumption that it is not a single strategy that must be selected. Rather, I might need to retrieve an object-graph that has several strategies ... [must not] binds the caller to the IOC Container ... Every new strategy must [not need to] be manually added to the list of bindings ... It would be nice if the IOC container simply gave a little more help.
I have used Simple Injector as my container of choice for some time now and one of the drivers for this decision is that it has extensive support for generics. It is through this feature that we will implement your requirements.
I'm a firm believer that the code should speak for itself so I'll jump right in ...
I have defined an extra class ContainerResolvedClass<T> to demonstrate that Simple Injector finds the right implementation(s) and successfully injects them into a constructor. That is the only reason for the class ContainerResolvedClass<T>. (This class exposes the handlers that are injected into it for test purposes via result.Handlers.)
This first test requires that we get one implementation back for the fictional class Type1:
[Test]
public void CompositeHandlerForType1_Resolves_WithAlphaHandler()
{
var container = this.ContainerFactory();
var result = container.GetInstance<ContainerResolvedClass<Type1>>();
var handlers = result.Handlers.Select(x => x.GetType());
Assert.That(handlers.Count(), Is.EqualTo(1));
Assert.That(handlers.Contains(typeof(AlphaHandler<Type1>)), Is.True);
}
This second test requires that we get one implementation back for the fictional class Type2:
[Test]
public void CompositeHandlerForType2_Resolves_WithAlphaHandler()
{
var container = this.ContainerFactory();
var result = container.GetInstance<ContainerResolvedClass<Type2>>();
var handlers = result.Handlers.Select(x => x.GetType());
Assert.That(handlers.Count(), Is.EqualTo(1));
Assert.That(handlers.Contains(typeof(BetaHandler<Type2>)), Is.True);
}
This third test requires that we get two implementations back for the fictional class Type3:
[Test]
public void CompositeHandlerForType3_Resolves_WithAlphaAndBetaHandlers()
{
var container = this.ContainerFactory();
var result = container.GetInstance<ContainerResolvedClass<Type3>>();
var handlers = result.Handlers.Select(x => x.GetType());
Assert.That(handlers.Count(), Is.EqualTo(2));
Assert.That(handlers.Contains(typeof(AlphaHandler<Type3>)), Is.True);
Assert.That(handlers.Contains(typeof(BetaHandler<Type3>)), Is.True);
}
These tests seems to meet your requirements and best of all no containers are harmed in the solution.
The trick is to use a combination of parameter objects and marker interfaces. The parameter objects contain the data for the behaviour (i.e. the IHandler's) and the marker interfaces govern which behaviours act on which parameter objects.
Here are the marker interfaces and parameter objects - you'll note that Type3 is marked with both marker interfaces:
private interface IAlpha { }
private interface IBeta { }
private class Type1 : IAlpha { }
private class Type2 : IBeta { }
private class Type3 : IAlpha, IBeta { }
Here are the behaviours (IHandler<T>'s):
private interface IHandler<T> { }
private class AlphaHandler<TAlpha> : IHandler<TAlpha> where TAlpha : IAlpha { }
private class BetaHandler<TBeta> : IHandler<TBeta> where TBeta : IBeta { }
This is the single method that will find all implementations of an open generic:
public IEnumerable<Type> GetLoadedOpenGenericImplementations(Type type)
{
var types =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from t in assembly.GetTypes()
where !t.IsAbstract
from i in t.GetInterfaces()
where i.IsGenericType
where i.GetGenericTypeDefinition() == type
select t;
return types;
}
And this is the code that configures the container for our tests:
private Container ContainerFactory()
{
var container = new Container();
var types = this.GetLoadedOpenGenericImplementations(typeof(IHandler<>));
container.RegisterAllOpenGeneric(typeof(IHandler<>), types);
container.RegisterOpenGeneric(
typeof(ContainerResolvedClass<>),
typeof(ContainerResolvedClass<>));
return container;
}
And finally, the test class ContainerResolvedClass<>
private class ContainerResolvedClass<T>
{
public readonly IEnumerable<IHandler<T>> Handlers;
public ContainerResolvedClass(IEnumerable<IHandler<T>> handlers)
{
this.Handlers = handlers;
}
}
I realise this post is a quite long, but I hope it clearly demonstrates a possible solution to your problem ...
This is a late response but maybe it will help others.
I have a pretty simple approach. I simply create a StrategyResolver to not be directly depending on Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Usage:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Registration:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Now, the nice thing about this is that I will never have to touch the StrategyResolver ever again when adding new strategies in the future.
It's very simple. Very clean and I kept the dependency on Unity to a strict minimum. The only time I would have touch the StrategyResolver is if I decide to change container technology which is very unlikely to happen.
Hope this helps!
I generally use a combination of your Abstract Factory and Named Bindings options. After trying many different approaches, I find this approach to be a decent balance.
What I do is create a factory that essentially wraps the instance of the container. See the section in Mark's article called Container-based Factory. As he suggests, I make this factory part of the composition root.
To make my code a little cleaner and less "magic string" based, I use an enum to denote the different possible strategies, and use the .ToString() method to register and resolve.
From your Cons of these approaches:
Typically binds the caller to the IOC Container
In this approach, the container is referenced in the factory, which is part of the Composition Root, so this is no longer an issue (in my opinion).
. . . and certainly requires the caller to know something about the strategy (such as the
name "Alpha").
Every new strategy must be manually added to the list
of bindings. This approach is not suitable for handling multiple
strategies in an object graph. In short, it does not meet
requirements.
At some point, code needs to be written to acknowledge the mapping between the structure that provides the implementation (container, provider, factory, etc.) and the code that requires it. I don't think you can get around this unless you want to use something that is purely convention-based.
The constructors of each strategy might have different needs. But now the responsibility of constructor injection has been transferred to the abstract factory from the container. In other words, every time a new strategy is added it may be necessary to modify the corresponding abstract factory.
This approach solves this concern completely.
Heavy use of strategies means heavy amounts of creating abstract factories.[...]
Yes, you will need one abstract factory for each set of strategies.
If this is a multi-threaded application and the "ambient context" is indeed provided by thread-local-storage, then by the time an object is using an injected abstract-factory to create the type it needs, it may be operating on a different thread which no longer has access to the necessary thread-local-storage value.
This will no longer be an issue since TLC will not be used.
I don't feel that there is a perfect solution, but this approach has worked well for me.

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