Creating objects with dependencies - dependency injection

前端 未结 3 1314
醉酒成梦
醉酒成梦 2021-01-06 11:21

Let\'s say we have class:

public class WithDependencies
{
  public WithDependencies(IAmDependencyOne first, IAmDependencyTwo second)
  // ...
}
相关标签:
3条回答
  • 2021-01-06 11:39

    It depends on the context, so it's impossible to provide a single answer. Conceptually you'd be doing something like this from the Composition Root:

    var wd = new WithDependencies(new DependencyOne(), new DependencyTwo());
    

    However, even in the absence of a DI Container, the above code isn't always unambiguously the correct answer. In some cases, you might want to share the same dependency among several consumers, like this:

    var dep1 = new DependencyOne();
    var wd = new WithDependencies(dep1, new DependencyTwo());
    var another = AnotherWithDependencies(dep1, new DependencyThree());
    

    In other cases, you might not want to share dependencies, in which case the first option is more correct.

    This is just a small glimpse of an entire dimension of DI concerned with Lifetime Management. Many DI Containers can take care of that for you, which is one excellent argument to prefer a DI Container over Poor Man's DI.

    Once you start using a DI Container, you should follow the Register Resolve Release pattern when resolving types, letting Auto-wiring take care of the actual composition:

    var wd = container.Resolve<WithDependencies>();
    

    The above example assumes that the container is already correctly configured.

    0 讨论(0)
  • 2021-01-06 11:46

    Sometimes I try to get rid of factories or at least not depend directly on them, so Dependency Injection (without factories) is useful of course.

    Therefore I use Google Juice, cause its a small little framework using Java Annotations and you can quickly change your injections / dependencies. Just take a look at it:

    http://code.google.com/p/google-guice/

    0 讨论(0)
  • 2021-01-06 11:49

    If you need to create a dependency which has its own dependencies, you can either A) do it yourself, or B) ask something else to do it for you. Option A negates the benefits of dependency injection (decoupling, etc.), so I would say option B is a better starting point. Now, we have chosen to use the factory pattern, no matter whether it takes the form of a service locator (i.e. IoC.Resolve), a static factory, or an instance factory. The point is that we have delegated that responsibility to an external authority.

    There are a number of trade-offs required for static accessors. (I went over them in another answer, so I won't repeat them here.) In order to avoid introducing a dependency on the infrastructure or the container, a solid option is to accept a factory for creating WithDependencies when we need an instance somewhere else:

    public class NeedsWithDependencies
    {
        private readonly IWithDependenciesFactory _withDependenciesFactory;
    
        public NeedsWithDependencies(IWithDependenciesFactory withDependenciesFactory)
        {
            _withDependenciesFactory = withDependenciesFactory;
        }
    
        public void Foo()
        {
            var withDependencies = _withDependenciesFactory.Create();
    
            ...Use the instance...
        }
    }
    

    Next, we can create a container-specific implementation of the factory:

    public class WithDependenciesFactory : IWithDependenciesFactory
    {
        private readonly IContainer _container;
    
        public WithDependenciesFactory(IContainer container)
        {
            _container = container
        }
    
        public WithDependencies Create()
        {
            return _container.Resolve<WithDependencies>();
        }
    }
    

    Now NeedsWithDependencies is completely isolated from any knowledge of how WithDependencies gets created; it also exposes all its dependencies in its constructor, instead of hiding dependencies on static accessors, making it easy to reuse and test.

    Defining all those factories can get a little cumbersome, though. I like Autofac's factory relationship type, which will detect parameters of the form Func<TDependency> and automatically inject a function which serves the same purpose as the hand-coded factory above:

    public class NeedsWithDependencies
    {
        private readonly Func<WithDependencies> _withDependenciesFactory;
    
        public NeedsWithDependencies(Func<WithDependencies> withDependenciesFactory)
        {
            _withDependenciesFactory = withDependenciesFactory;
        }
    
        public void Foo()
        {
            var withDependencies = _withDependenciesFactory();
    
            ...Use the instance...
        }
    }
    

    It also works great with runtime parameters:

    public class NeedsWithDependencies
    {
        private readonly Func<int, WithDependencies> _withDependenciesFactory;
    
        public NeedsWithDependencies(Func<int, WithDependencies> withDependenciesFactory)
        {
            _withDependenciesFactory = withDependenciesFactory;
        }
    
        public void Foo(int x)
        {
            var withDependencies = _withDependenciesFactory(x);
    
            ...Use the instance...
        }
    }
    
    0 讨论(0)
提交回复
热议问题