An introduction to DI and IOC using a simple console application.
• Senior Consultant for Polaris Solutions, a technology based
consulting firm based out of Chicago, Denver, and St. Louis.
• Been in software development for almost thirty years,
programming in various languages and operating systems.
• Worked for startups, fortune 500 companies, and consulting
firms.
• A firm believer in the idea that Confucius expressed, “Choose a
job you love, and you will never have to work a day in your life.”
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• We will work through several examples transforming a very simple
program to a very complex program, exploring along the way the
concepts of dependency injection, inversion of control and AOP.
• Present these concepts through examples written in c#,
progressively introducing concepts in a compare and contrast
fashion.
• Learning Objectives:
• What is Inversion of Control and Dependency Injection?
• Are they always paired together?
• See Dependency Injection and Inversion of Control work in a simple scenario.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• https://github.com/polarissolutions/DIIOC_Presentation
• In addition to a master branch, contains branches which align
with the presentation
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Because the dateHelper class creates it’s own instance of the
date object, the class becomes really difficult to test.
• To test you would either need to change the class for a
particular case or set a break point and change during runtime.
• Extremely difficult to unit test, cannot mock up a date object
(yes you can place under a shim context but more difficult)
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• A dependency is an object that can be used (a service).
• An injection is the passing of a dependency to a dependent
object (a client) that would use it.
• The service is made part of the client's state.
• Passing the service to the client, rather than allowing a
client to build or find the service, is the fundamental
requirement of the pattern.
• Source - https://en.wikipedia.org/wiki/Dependency_injection
• Can be used independently of IOC Container
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• It is more generally accepted to pass an object which
implements an interface, although in our dateHelper class we
are passing a concrete implementation to start.
• Coding against the contract (Interface) allows you to pass any
concrete class which implements the contract.
• Example:
• Public class SQLDBConnection : IDBConnection
• Public class ODBCConnection : IDBConnection
• All classes share the same IDBConnection contract definition.
• Programming against the interface allows you not to worry
about implementation
• Factories can be used to create the concrete class
• IDBConnection = DBFactory(“configfile”)
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Add the following:
• Logger project
• Façade project
• Interfaces project
• Hello project
• Date Print project.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• You can consider an interface a contract which you agree to
implement in a class.
• You can program against the interface / contract instead of a
concrete class.
• Interfaces can exist in as part of the same project (default).
• Interfaces can exist in a separate project from the project that
implements them as long as the project references the interface
project.
• You might use this to publish a list of interfaces publicly that someone
could use to extend the software.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Inject the dependency through a constructor or method
• The dependency object can be a concrete class created using a
new (new object)
• The dependency object can be a concrete class created as an
interface created using a factory.
• The dependency can be created using a container which will
create the concrete object based of the interface.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Traditionally the flow of the business logic is determined by
objects that are statically bound (referenced) to one another.
• With inversion of control, the flow depends on the object graph
that is built up during program execution. Such a dynamic flow
is made possible by object interactions being defined through
abstractions.
• In dependency injection, a dependent object or module is
coupled to the object it needs at run time.
• Source - https://en.wikipedia.org/wiki/Inversion_of_control
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Consider using Inversion of Control if you need:
• Significant extensibility
• A generic configuration tool
• Want to support multiple deployment configurations
• Use a Test-Driven Development philosophy or want to largely automate
testing
• Want to isolate a troublesome subsystem or provide smooth migration
paths away from legacy interfaces
• Need a great deal of configurable properties or plugin hot spots
• Break hard dependencies in projects
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Typically objects created can be configured for different life
times:
• Typically:
• Per Request - The default operation. A new instance will be created for each
request.
• Singleton - A single instance will be shared across all requests
• Depending on circumstances:
• Thread Local - A single instance will be created for each requesting thread.
Caches the instances with Thread Local Storage.
• HttpContext - A single instance will be created for each HttpContext. Caches the
instances in the HttpContext.Items collection.
• HttpSession - A single instance will be created for each HttpSession. Caches the
instances in the HttpContext.Session collection. Use with caution.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Builder object to initialize objects and provide the required
dependencies to the object through a constructor (typically).
• Service Locator pattern introduces a locator object to resolve
dependencies.
• You will see examples of both the Service Locator pattern as
well as Dependency Constructor injection
• https://msdn.microsoft.com/en-us/library/ff921087.aspx
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• StructureMap *
• Ninject
• Autofac **
• Microsoft Unity
• Castle Windsor
• Spring.Net
• * Examples in structure map
• ** We may also explore Autofac (time permitting)
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Use NuGet to get proper package for container.
• We will add a new project called Injector.
• Injector will provide ContainerBootStrapper which will be responsible
for wiring up the concrete classes to inject into the classes
constructors.
• The projects which change include:
• DIIOC - using container to return concrete object for logger and
facade.
• DisplayDateClass - Now logs as well and has the logger injected
as part of the constructor.
• The InterfaceClass now has the contracts defined for all
projects.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• We break the dependency of including each object in the
container to resolve.
• Add an example of AOP (Aspect Oriented Programming) where
the real concrete class is wrapped with a similar class as a
proxy and added functionality for centralized functionality.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• To break dependency from the bootstrapper setting the log
parameters, the loggerclass was changed to responsible for
itself.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Notice class has two constructors.
• Pass in a date object.
• Pass in a date object and a logger object.
• Remember when using IOC the container will typically be
greedy and fill the constructor with the most parameters.
• Internally we have a date factory to return todays date which is
instantiated through the internal IDateFactory interface.
Scanner will automatically map
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• So that we did not need to set the current date as part of the
scanner, added a private DateFactory to pass in the current
date.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• You can think of the container as a dictionary of concrete
classes which have a key of the interface
• The Service Locator will return a concrete type using the
interface as the key. Basically a factory pattern. Especially in
the case of the logger which has no dependencies.
• The builder will create not only the concrete class requested but
also the object graph for any dependent objects.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• In computing, aspect-oriented programming (AOP) is a
programming paradigm that aims to increase modularity by
allowing the separation of cross-cutting concerns.
• This allows behaviors that are not central to the business logic
to be added to a program without cluttering the code core to the
functionality.
• Examples include:
• Logging
• Error Handling
• Source - https://en.wikipedia.org/wiki/Aspect-
oriented_programming
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• In our StructureMap solution, AOP is
implemented as a Decorator pattern
• In our Autofac solution, AOP is
implemented as a Interceptor pattern
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Since the projects are no longer referenced by the core program (only interface and injector are)
they do not automatically move to the application bin directory. This needs to be done for each
project built.
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• You need to set the build order for IOC so that all projects are built first.
• Show example of Injector using:
• AutoFac
• Show in further detail the AOP implementation for Autofac.
• Discuss Unity and XML configuration
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
• Steven.Contos@PolarisSolutions.com
• www.TheOldManAndTheCSharp.com
• https://www.slideshare.net/StevenContos
• Wikipedia links:
• https://en.wikipedia.org/wiki/Dependency_injection
• https://en.wikipedia.org/wiki/Inversion_of_control
• https://en.wikipedia.org/wiki/Aspect-oriented_programming
• .Net Core – built in dependency injection.
• https://andrewlock.net/using-dependency-injection-in-a-net-core-
console-application
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp
Steven.Contos@PolarisSolutions.com
Blog:TheOldManAndTheCSharp

Polaris presentation ioc - code conference

  • 1.
    An introduction toDI and IOC using a simple console application.
  • 2.
    • Senior Consultantfor Polaris Solutions, a technology based consulting firm based out of Chicago, Denver, and St. Louis. • Been in software development for almost thirty years, programming in various languages and operating systems. • Worked for startups, fortune 500 companies, and consulting firms. • A firm believer in the idea that Confucius expressed, “Choose a job you love, and you will never have to work a day in your life.” Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 3.
    • We willwork through several examples transforming a very simple program to a very complex program, exploring along the way the concepts of dependency injection, inversion of control and AOP. • Present these concepts through examples written in c#, progressively introducing concepts in a compare and contrast fashion. • Learning Objectives: • What is Inversion of Control and Dependency Injection? • Are they always paired together? • See Dependency Injection and Inversion of Control work in a simple scenario. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 4.
  • 5.
  • 6.
  • 7.
    • Because thedateHelper class creates it’s own instance of the date object, the class becomes really difficult to test. • To test you would either need to change the class for a particular case or set a break point and change during runtime. • Extremely difficult to unit test, cannot mock up a date object (yes you can place under a shim context but more difficult) Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 8.
  • 9.
  • 10.
    • A dependencyis an object that can be used (a service). • An injection is the passing of a dependency to a dependent object (a client) that would use it. • The service is made part of the client's state. • Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern. • Source - https://en.wikipedia.org/wiki/Dependency_injection • Can be used independently of IOC Container Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 11.
  • 12.
  • 13.
    • It ismore generally accepted to pass an object which implements an interface, although in our dateHelper class we are passing a concrete implementation to start. • Coding against the contract (Interface) allows you to pass any concrete class which implements the contract. • Example: • Public class SQLDBConnection : IDBConnection • Public class ODBCConnection : IDBConnection • All classes share the same IDBConnection contract definition. • Programming against the interface allows you not to worry about implementation • Factories can be used to create the concrete class • IDBConnection = DBFactory(“configfile”) Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 14.
    • Add thefollowing: • Logger project • Façade project • Interfaces project • Hello project • Date Print project. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 15.
    • You canconsider an interface a contract which you agree to implement in a class. • You can program against the interface / contract instead of a concrete class. • Interfaces can exist in as part of the same project (default). • Interfaces can exist in a separate project from the project that implements them as long as the project references the interface project. • You might use this to publish a list of interfaces publicly that someone could use to extend the software. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 16.
  • 17.
  • 18.
    • Inject thedependency through a constructor or method • The dependency object can be a concrete class created using a new (new object) • The dependency object can be a concrete class created as an interface created using a factory. • The dependency can be created using a container which will create the concrete object based of the interface. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 19.
  • 20.
    • Traditionally theflow of the business logic is determined by objects that are statically bound (referenced) to one another. • With inversion of control, the flow depends on the object graph that is built up during program execution. Such a dynamic flow is made possible by object interactions being defined through abstractions. • In dependency injection, a dependent object or module is coupled to the object it needs at run time. • Source - https://en.wikipedia.org/wiki/Inversion_of_control Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 21.
    • Consider usingInversion of Control if you need: • Significant extensibility • A generic configuration tool • Want to support multiple deployment configurations • Use a Test-Driven Development philosophy or want to largely automate testing • Want to isolate a troublesome subsystem or provide smooth migration paths away from legacy interfaces • Need a great deal of configurable properties or plugin hot spots • Break hard dependencies in projects Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 22.
    • Typically objectscreated can be configured for different life times: • Typically: • Per Request - The default operation. A new instance will be created for each request. • Singleton - A single instance will be shared across all requests • Depending on circumstances: • Thread Local - A single instance will be created for each requesting thread. Caches the instances with Thread Local Storage. • HttpContext - A single instance will be created for each HttpContext. Caches the instances in the HttpContext.Items collection. • HttpSession - A single instance will be created for each HttpSession. Caches the instances in the HttpContext.Session collection. Use with caution. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 23.
    • Builder objectto initialize objects and provide the required dependencies to the object through a constructor (typically). • Service Locator pattern introduces a locator object to resolve dependencies. • You will see examples of both the Service Locator pattern as well as Dependency Constructor injection • https://msdn.microsoft.com/en-us/library/ff921087.aspx Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 24.
    • StructureMap * •Ninject • Autofac ** • Microsoft Unity • Castle Windsor • Spring.Net • * Examples in structure map • ** We may also explore Autofac (time permitting) Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 25.
    • Use NuGetto get proper package for container. • We will add a new project called Injector. • Injector will provide ContainerBootStrapper which will be responsible for wiring up the concrete classes to inject into the classes constructors. • The projects which change include: • DIIOC - using container to return concrete object for logger and facade. • DisplayDateClass - Now logs as well and has the logger injected as part of the constructor. • The InterfaceClass now has the contracts defined for all projects. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
    • We breakthe dependency of including each object in the container to resolve. • Add an example of AOP (Aspect Oriented Programming) where the real concrete class is wrapped with a similar class as a proxy and added functionality for centralized functionality. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 31.
  • 32.
    • To breakdependency from the bootstrapper setting the log parameters, the loggerclass was changed to responsible for itself. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 33.
    • Notice classhas two constructors. • Pass in a date object. • Pass in a date object and a logger object. • Remember when using IOC the container will typically be greedy and fill the constructor with the most parameters. • Internally we have a date factory to return todays date which is instantiated through the internal IDateFactory interface. Scanner will automatically map Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 34.
    • So thatwe did not need to set the current date as part of the scanner, added a private DateFactory to pass in the current date. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 35.
  • 36.
    • You canthink of the container as a dictionary of concrete classes which have a key of the interface • The Service Locator will return a concrete type using the interface as the key. Basically a factory pattern. Especially in the case of the logger which has no dependencies. • The builder will create not only the concrete class requested but also the object graph for any dependent objects. Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 37.
    • In computing,aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. • This allows behaviors that are not central to the business logic to be added to a program without cluttering the code core to the functionality. • Examples include: • Logging • Error Handling • Source - https://en.wikipedia.org/wiki/Aspect- oriented_programming Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 38.
  • 39.
    • In ourStructureMap solution, AOP is implemented as a Decorator pattern • In our Autofac solution, AOP is implemented as a Interceptor pattern Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 40.
    Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp • Since theprojects are no longer referenced by the core program (only interface and injector are) they do not automatically move to the application bin directory. This needs to be done for each project built.
  • 41.
    Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp • You needto set the build order for IOC so that all projects are built first.
  • 42.
    • Show exampleof Injector using: • AutoFac • Show in further detail the AOP implementation for Autofac. • Discuss Unity and XML configuration Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 43.
  • 44.
  • 45.
    • Steven.Contos@PolarisSolutions.com • www.TheOldManAndTheCSharp.com •https://www.slideshare.net/StevenContos • Wikipedia links: • https://en.wikipedia.org/wiki/Dependency_injection • https://en.wikipedia.org/wiki/Inversion_of_control • https://en.wikipedia.org/wiki/Aspect-oriented_programming • .Net Core – built in dependency injection. • https://andrewlock.net/using-dependency-injection-in-a-net-core- console-application Steven.Contos@PolarisSolutions.com Blog:TheOldManAndTheCSharp
  • 46.

Editor's Notes

  • #8 How many times have you had to set a breakpoint and change a value then continue? I know I have Testing for future or past dates are extremely difficult.
  • #11 Most important part is that you can use this in addition to Inversion of Control to solve problems.
  • #12 Problem with the datehelper is that it only uses the current time. It is dependent on the current time. We will change to pass in the dependent object, thereby doing dependency injection!
  • #13 How many times have you had to set a breakpoint and change a value then continue? I know I have
  • #14 The service client can changed without an effect as long as it implements the same interface. The example here is typical of Microsoft Enterprise Library for database connectivity.
  • #15 Interfaces project will be explained soon
  • #17 The logger and the loglevel constants are defined in the interfaces project The class
  • #18 Note that this version of the interfaceClass project only contains what is needed for the logger and because we assign the interface to the concrete class, the concrete class has a hard dependency.
  • #21 Statically bound means inclusion of references.
  • #22 To start we are going to use structure map, then time permitting we will show examples in other frameworks as well.
  • #23 Our project will be per request and Singleton
  • #26 Interfaces can also be specified in the same project as the concrete implementation, but that would not allow us to separate concrete class later on. You should Enable NuGet package restore to ensure that you automatically get required assemblies. 
  • #27 In the case of the logger we are instantiating directly. You can think of GetInstance as returning a dictionary of concrete classes by key. Although the Façade class is instantiated similarly, as the façade class and it dependencies are created, the container will manage to resolve its dependencies.
  • #28 In the constructor, we create a new container object which we configure. The first three lines which are of format x.For<interface>().Use<concrete>() map the concrete class to us for the interface. Notice we pass in the DateTime.Now to the constructor. The fourth line is similar but changes it's lifetime to singleton and then sets the parameters to pass into the concrete class Logger.  
  • #29 Notice two constructor with different signatures. Most containers are greedy and will look for the constructor with the most parameters.
  • #30 DIIOC.exe now only requires a reference to Injector and Interface. Now the Main, Façade and DisplayDateClass all log something. Notice now that since injector still needs a reference to each object to resolve, all the project DLLs will still be imported automatically into the application bin directory. Noted with grey arrows, project reference.
  • #32 No longer <Interface>.(Concrete), now scanning the assemblies folder for objects that startwith. Could just simply scan all assemblies and would work as well. Done to show differences. Note lifetime of logger. Note AOP for façade. We can no longer pass in parameters to instances and must instead create inputs via factory methods
  • #33 This is just a good to know why it changed. Reads information from the config file.
  • #36 IOC now only has a hard reference to Injector DLL and InterfaceClass DLL and all the other objects can be replaced with any object which references the interfaces. I.e. debug versions of a concrete class, a mock object etc.
  • #39 Notice this is a class which also implements the interface we are trying to proxy You can change DisplayStrings to throw an error and show this working.
  • #40 Both the Decorator and Interceptor patterns allow multiple cross cutting concerns to be implemented. If we have time we can open up the Autofac version and show the interceptor pattern.
  • #43 If we have enough time, we can discuss other projects included