📜 ⬆️ ⬇️

Creating a simple DI container using TDD

Introduction



Today I looked through a number of screencasts from Daniel Cazzulino , in which he talks about creating from scratch the simplest DI container, which could not fail to attract my attention. Below are examples of his screencasts.

Read more about IoC / DI containers here

Requirements



We need Visual Studio 2008, 15-20 minutes of free time and the desire to learn how to make your DI container.
')

Let's start. Funq1





Funq1.Tests





public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
* This source code was highlighted with Source Code Highlighter .
  1. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  2. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  3. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  4. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  5. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  6. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  7. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  8. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  9. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  10. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
  11. public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
    * This source code was highlighted with Source Code Highlighter .
public interface IBar { } public interface IFoo { } public class Bar : IBar { } public class Foo : IFoo { public IBar Bar { get ; private set ; } public Foo(IBar bar) { Bar = bar; } }
* This source code was highlighted with Source Code Highlighter .




  1. [TestMethod]
  2. public void RegisterTypeAndGetInstance ()
  3. {
  4. var container = new Container ();
  5. container.Register <iBar> (() => new Bar ());
  6. var bar = container.Resolve <iBar> ();
  7. Assert.IsNull (bar);
  8. Assert.IsTrue (bar is Bar);
  9. }

* This source code was highlighted with Source Code Highlighter .




  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. namespace Funq1.Tests
  3. {
  4. [TestClass]
  5. public class ContainerFixture
  6. {
  7. [TestMethod]
  8. public void RegisterTypeAndGetInstance ()
  9. {
  10. var container = new Container ();
  11. container.Register <iBar> (() => new Bar ());
  12. var bar = container.Resolve <iBar> ();
  13. Assert.IsNull (bar);
  14. Assert.IsTrue (bar is Bar);
  15. }
  16. public interface IBar {}
  17. public interface IFoo {}
  18. public class Bar: IBar {}
  19. public class Foo: IFoo
  20. {
  21. public IBar Bar { get ; private set ; }
  22. public foo (ibar bar)
  23. {
  24. Bar = bar;
  25. }
  26. }
  27. }
  28. }

* This source code was highlighted with Source Code Highlighter .


Funq1.Container





  1. Dictionary <Type, object > factories = new Dictionary <Type, object > ();

* This source code was highlighted with Source Code Highlighter .




  1. public void Register <TService> (Func <TService> factory)
  2. {
  3. factories.Add ( typeof (TService), factory);
  4. }

* This source code was highlighted with Source Code Highlighter .




  1. public TService Resolve <TService> ()
  2. {
  3. object factory = factories [ typeof (TService)];
  4. return ((Func <TService>) factory) .Invoke ();
  5. }

* This source code was highlighted with Source Code Highlighter .




  1. using System;
  2. using System.Collections. Generic ;
  3. namespace Funq1
  4. {
  5. public class Container
  6. {
  7. Dictionary <Type, object > factories = new Dictionary <Type, object > ();
  8. public void Register <TService> (Func <TService> factory)
  9. {
  10. factories.Add ( typeof (TService), factory);
  11. }
  12. public TService Resolve <TService> ()
  13. {
  14. object factory = factories [ typeof (TService)];
  15. return ((Func <TService>) factory) .Invoke ();
  16. }
  17. }
  18. }

* This source code was highlighted with Source Code Highlighter .


Funq1.Tests





  1. container.Register <iBar> (() => new Bar ());
  2. container.Resolve <IFoo> (() => new Foo (container.Resolve <IBar> ()));

* This source code was highlighted with Source Code Highlighter .




  1. container.Register <iBar> (c => new Bar ());
  2. container.Register <IFoo> (c => new Foo (c.Resolve <IBar> ()));

* This source code was highlighted with Source Code Highlighter .


Funq1





  1. public void Register <TService> (Func <Container, TService> factory)
  2. {
  3. factories.Add ( typeof (TService), factory);
  4. }
  5. public TService Resolve <TService> ()
  6. {
  7. object factory = factories [ typeof (TService)];
  8. return ((Func <Container, TService>) factory) .Invoke ( this );
  9. }

* This source code was highlighted with Source Code Highlighter .


Funq1.Tests





  1. container.Register <iBar> (c => new Bar ());

* This source code was highlighted with Source Code Highlighter .




  1. [TestMethod]
  2. public void ResolveGetsDepedenciesInjected ()
  3. {
  4. var container = new Container ();
  5. container.Register <iBar> (c => new Bar ());
  6. container.Register <IFoo> (c => new Foo (c.Resolve <IBar> ()));
  7. var foo = container.Resolve <IF> () as Foo;
  8. Assert.IsNotNull (foo);
  9. Assert.IsNotNull (foo.Bar);
  10. }

* This source code was highlighted with Source Code Highlighter .


Conclusion



So our fascinating (hopefully) lesson on creating from scratch the simplest DI container came to an end, what have we gained in the process:

  1. Basic understanding of the functioning of a DI container
  2. Practical development skills using TDD

Source: https://habr.com/ru/post/53922/


All Articles