Dependency Injection

Sign in to queue

Description

In this episode, Robert is joined by Miguel Castro, who explains dependency injection, which makes it easy to resolve classes at any level in any size object hierarchy, all the while making your application much easier to test. Miguel demystifies this important technique and explains why and how you should use it in every project. 

Embed

Download

The Discussion

  • User profile image
    wkempf

    Pretty good "webinar". In the video it was mentioned (paraphrasing) all DI containers do reflection. This actually isn't true. What's true is that MOST containers do reflection, but there are some out there that use no reflection. In fact, it just takes a few lines of code to create a container that doesn't use reflection at all.

    void Main()
    {
        var container = new Container();
        container.Register<ILogger>(c => new Logger());
        container.Register<Foo>(c => new Foo(c.Resolve<ILogger>()));
        var foo = container.Resolve<Foo>();
        foo.DoSomething();
    }
    
    public class Container
    {
        private readonly Dictionary<Type, Func<Container, object>> registry
            = new Dictionary<Type, Func<Container, object>>();
        
        public void Register<T>(Func<Container, T> factory) =>
            registry.Add(typeof(T), c => factory(c));
        
        public T Resolve<T>() => (T)registry[typeof(T)].Invoke(this);
    }
    
    public interface ILogger
    {
        void Log(string message);
    }
    
    public class Logger : ILogger
    {
        public void Log(string message) => message.Dump();
    }
    
    public class Foo
    {
        private readonly ILogger logger;
        
        public Foo(ILogger logger) => this.logger = logger;
        
        public void DoSomething() => logger.Log("Log something.");
    }

    I wrote that code in LinqPad, so there's some adjustments to make if you put this into a console application (replace the call to "Dump" with Console.WriteLine calls instead, basically), and I've used several new C# language features to condense the code as much as possible, but this should be very understandable to anyone. There's zero reflection in this code, and yet I'm using a container to resolve dependencies.

    Ignoring the fact that this isn't production quality code (no error handling, for instance), this naïve container is fully usable in any application you'd write. The drawbacks: registration is more complex and there's some features missing, like the ability to tell the container to only ever create one instance of the ILogger no matter how many times you inject it, or to handle lifetime issues. There are some containers available in NuGet that properly handle errors and add some of the missing features, but continue to use the same "no reflection" design this simple code does.

    As for concern about reflection cost if a container does use it... a good container does reflection only during registration/container build time. Internally it's using the same mechanism this naïve code uses, associating a type with a factory delegate, so when you Resolve there's no reflection at all. This means there's very little impact to the performance of your code (the only cost is a minor cost at startup and some dictionary lookups when you resolve). So the speaker was absolutely correct... you'll be hard pressed to notice any performance differences when you use a DI container.

  • User profile image
    ershadnozari

    Great episode! Love hearing Miguel Castro speak.

  • User profile image
    mkkkk

    When he was trying to explain registration the camera should have been on the code, not their backs.

  • User profile image
    Tony

    Still way too confusing. You need to teach dependency injection using a very simple example and then build on that example. Your example is way too complex to start. The sidekick is nothing but a distraction that causes you to jump from topic to topic thus loosing the audience. You seem to go off the rails and talk about things that take you away from the task at hand. Stay focused. Teach, don't B.S. about products and other things that have nothing to do with learning the concept of dependency injection.

    I tuned in hoping to learn dependency injection. Instead I left not knowing any more than when I started.

  • User profile image
    Norm

    Great job Miguel!!!

  • User profile image
    Mike

    Nice webinar. Wouldn't there be a registration problem if your code had more than one class that implemented a particular interface? As a contrived example, say you have IPet interface and Dog, Cat classes that implement IPet. When your code passes in IPet to a method (e.g. void Speak(IPet pet) {...}) how is the concrete class determined?

    Thanks - Mike.

  • User profile image
    Filipe

    Excelent episode! Where can I get the sample source code??

  • User profile image
    chanmm

    How do you measure the productivities with dependent injection and without dependency injection for a developer?

    By doing this is also adding more run time errors than the compile time errors for example,

    t.name.Endswith("Processor")

    if someone type

    t.name.Endswith("Processors")

    I bet C# got no way to detect this is actually a type error or data type not exist.

    What is wrong with hitting a database if you have a proper dev environment? In the real production environment you need to hit the database so it is not a bad idea to test with the real database than mocking this or faking that.

  • User profile image
    Goran

    Nice explanation! Is the demo code available for download?

  • User profile image
    Niner377430

    Although the subject matter was good and presenter very knowledgeable they forgot their audience. Half of the the presentation was spent with their backs to the camera discussing code that could not be scene.

  • User profile image
    rogreen

    @Niner377430: Sorry about that. :( We will try not to do that in the future. 

    Robert

Add Your 2 Cents