ioc in unity
TRANSCRIPT
IoC in Microsoft Unity
Francesco Garavaglia
03/2016
Agenda The Problem
Composition by Examples
Inversion of Control (IoC)
Dependency Injection Microsoft
Unity
2
What problems
are we trying to
solve?
3
4
The Problem
We live in an age where writing software to a given set of requirements is no longer enough.
We have to maintain and change existing code.
Code quality ( What’s Bad ) R.Martin 1996
- Rigid (hard to modify)
- Fragile ( errors occur on almost every change)
- Immobile (not reusable)
The Problem
How?Our solutions should be:
• Modular
• Testable
• Adaptive to change
• Whatever you want
5
How?Our solutions should be:
• Modular
• Testable
• Adaptive to change
• Whatever you want
6
7
We need a glossary
Service—An object that performs a well-defined function when called upon
Client—Any consumer of a service; an object that calls upon a service to perform a well-
understood function
Dependency—A specific service that is required by another object to fulfill its function.
Dependent—A client object that needs a dependency (or dependencies) in order to perform its
function.
The Problem
Composition:
OLD SCHOOL
8
9
Ex1:CompositionComposition by Examples
10
Ex1: Composition
public class SpellCheckerService{}
public class TextEditor
{
private SpellCheckerService _spellCheckerService;
public TextEditor()
{
_spellCheckerService = new SpellCheckerService();
}
}
class Program
{
static void Main(string[] args)
{
TextEditor textEditor = new TextEditor();
}
}
TextEditor
SpellChecker
Composition by Examples
11
Ex1: Composition
• SimpleWhat is Good
• It’s not testable
• It’s hard to maintain/change
What is Bad
Composition by Examples
Composition:
NEW SCHOOL
12
13
Better approach
TextEditor
+ CheckSpelling() : bool
SpellCheckerServ ice
+ CheckSpelling() : string
«interface»
ISpellCheckerServ ice
+ CheckSpelling() : string
Dependency Inversion
A.High-level modules should not
depend on low-level modules. Both
should depend on abstractions.
B. Abstractions should not depend
upon details. Details should depend
upon abstractions.
Robert C. Martin 1996
Composition by Examples
14
Context
Granny
+ Eat() : void
«interface»
IAppleProv ider
+ GetApple() : IApple
RedAppleProv ider
+ GetApple() : IApple
GoldenAppleProv ider
+ GetApple() : IApple
«interface»
IPillProv ider
ConcretePillProv ider
Context
Composition by Examples
15
Ex2:Loose Coupling
public class TextEditor
{
private readonly ISpellCheckerService _spellCheckerService;
public TextEditor(ISpellCheckerService spellCheckerService)
{
_spellCheckerService = spellCheckerService;
}
public string CheckSpelling()
{
return _spellCheckerService.CheckSpelling();
}
}
Composition by Examples
16
Ex2: Unit Testing
// Mock
ISpellCheckerService mock = new SpellCheckerServiceMock();
// Instantiate
TextEditor textEditor = new TextEditor(mock);
// Check
Assert.AreEqual(“Mock”, textEditor.CheckSpelling());
Composition by Examples
17
Ex2: Good vs Bad
• Dependencies are obvious.
• Dependency resolution is not encapsulated.
• Unit Testing is applicable
• Architecture is much better
What is Good
• We are resolving dependencies manually while creating instances of TextEditor.
What is Bad
TextEditor lost its “Sovereignty” and is not able to resolve dependencies by himself.
Composition by Examples
18
Ex3: Using FactoryComposition by Examples
19
20
21
22
23
24
25
Factory
TextEditorFactory
+ GetEnglishTextEditor() : TextEditor
+ GetFrenchTextEditor() : TextEditor
TextEditor
FrenchSpellCheckerServ ice
«interface»
ISpellCheckerServ ice
EnglishSpellCheckerServ ice
Composition by Examples
26
What changed
Any required combination of Text Editor and Spell Checking Service is created by object factory.
•It’s testable
•No manual wiring
What is Good
•You have to maintain factory or service locator
•The more combinations the more methods we have in factory.
•Your code knows about the specific factory or factory interface. This means that infrastructure logic is mixed with business logic.
•Factory may have states.
What is Bad
Composition by Examples
27
Ex4: Service Locator
Unfortunately, being a kind of Factory, Service Locators suffer from the same problems
of testability and shared state.
Composition by Examples
28
What are we looking for?Composition by Examples
Inversion of
Control
HOLLYWOOD PRINCIPLE:
DON’T CALL ME, I’LL CALL YOU
29
30
Inversion of Control
IoC – is a common characteristic of
frameworks.
According to Martin Fowler the etymology of
the phrase dates back to 1988.
Inversion of Control
31
Dependency Injection
DI is a kind of IoC
Inversion of Control is too generic a term
DI pattern – describes the approach used to lookup a dependency.
Dependency resolution is moved to Framework.
Inversion of Control
32
SpellCheckerServ ice
+ CheckSpelling() : bool
TextEditor
+ CheckSpelling() : bool
«interface»
ISpellCheckerServ ice
We have already prepared basis
Loosely
coupled
structure
Inversion of Control
It’s time to
introduce new
role: Injector
Injector(sometimes referred to as
a provider or container)
33
Unity
34
35
Ex5: Unity
using Microsoft.Practices.Unity;
UnityContainer container = new UnityContainer();
container.RegisterType<ISpellCheckerService, SpellCheckingService>();
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
36
What changed
Unity container now resolves dependencies
•Automated dependency resolution
•Business logic and infrastructure are decoupled.
What is Good
What is Bad
DI with Unity
37
Injection Types
Interface injection (by Martin Fowler)
Constructor Injection (by Martin Fowler)
Setter injection (by Martin Fowler)
Method call injection (Unity)
Method decorator injection (Guice)
DI with Unity
38
Unity Configuration
<configSections><section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Pr
actices.Unity.Configuration"/></configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"><alias alias="ISpellCheckerService" type="Unity.Config.ISpellCheckerService, Unity.Config" /><alias alias="SpellCheckingService" type="Unity.Config.SpellCheckingService, Unity.Config" /><namespace name="Unity.Config" /><assembly name="Unity.Config" />
<container><register type="ISpellCheckerService" mapTo="SpellCheckingService" />
</container></unity>
DI with Unity
39
Unity Configuration
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
UnityContainer container = new UnityContainer();
container.LoadConfiguration();
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
40
Dependency treeDI with Unity
41
Dependency tree
public interface IAdditionalDependency{}
public class AdditionalDependency : IAdditionalDependency{}
public class SpellCheckingService: ISpellCheckerService {
public SpellCheckingService( IAdditionalDependency dependency){}
}
UnityContainer container = new UnityContainer();
container.RegisterType<ISpellCheckerService, SpellCheckingService>();
container.RegisterType<IAdditionalDependency, AdditionalDependency>();
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
42
Dependency tree
SpellCheckerServ ice
+ CheckSpelling() : bool
TextEditor
+ CheckSpelling() : bool
«interface»
ISpellCheckerServ ice
AdditionalDependency
+ CheckSpelling() : bool
«interface»
IAditionalDependenct
DI with Unity
43
Defining Injection Constructor
public class TextEditor{
private readonly ISpellCheckerService _spellCheckerService;
[InjectionConstructor]public TextEditor(ISpellCheckerService spellCheckerService){
_spellCheckerService = spellCheckerService;}
public TextEditor(ISpellCheckerService spellCheckerService,string name){
_spellCheckerService = spellCheckerService;}
}
DI with Unity
44
Property Injection
public class TextEditor{
public ISpellCheckerService SpellCheckerService {get; set;}
[Dependency]public ISpellCheckerService YetAnotherSpellcheckerService{get;set;}
}
UnityContainer container = new UnityContainer();container.RegisterType<TextEditor>(new InjectionProperty("SpellCheckerService"));container.RegisterType<ISpellCheckerService, SpellCheckingService>();
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
45
Method call injection
public class TextEditor{
public ISpellCheckerService SpellcheckerService {get; set;}
public void Initialize (ISpellCheckerService spellcheckerService){
_spellCheckerService = spellcheckerService;}
}
UnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckerService, SpellCheckingService>();
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
46
Lifetime Managers
TransientLifetimeManagerReturns a new instance of the requested type for each call. (default behavior)
ContainerControlledLifetimeManagerImplements a singleton behavior for objects. The object is disposed of when you dispose of the container.
ExternallyControlledLifetimeManagerImplements a singleton behavior but the container doesn't hold a reference to object which will be disposed of when out of scope.
HierarchicalifetimeManagerImplements a singleton behavior for objects. However, child containers don't share instances with parents.
PerResolveLifetimeManagerImplements a behavior similar to the transient lifetime manager except that instances are reused across build-ups of the object graph.
PerThreadLifetimeManagerImplements a singleton behavior for objects but limited to the current thread.
DI with Unity
47
Unity Singleton
UnityContainer container = new UnityContainer();
container.RegisterType<ISpellCheckerService, SpellCheckingService>(new
ContainerControlledLifetimeManager());
TextEditor textEditor = container.Resolve<TextEditor>();
DI with Unity
48
Container HierarchyDI with Unity
49
Unity Limitations
• When your objects and classes have no dependencies on other objects or classes.
• When your dependencies are very simple and do not require abstraction.
DI with Unity
50
References
Martin Fowler – Dependency Injection
http://martinfowler.com/articles/injection.html
R. Martin - Dependency Inversion principle
http://www.objectmentor.com/resources/articles/dip.pdf
Developer's Guide to Dependency Injection Using Unity
https://msdn.microsoft.com/en-us/library/dn223671(v=pandp.30).aspx