0

Sometimes when I use dependency injection (Ninject shown here as an example), we will need to construct dependencies using parameters that are only available at run time.

This is where the abstract factory pattern helps and I understand most of it.

However is there a reason why should/shouldn't we inject the value produced by the factory into the consumer directly instead?

Here's an example of it, assuming Foo can only be constructed by a run time string parameter and IFooFactory being the interface constructing Foo:

  • Inject the abstract factory into the consumer

    public class ConsumerService : IConsumerService
    {
         private readonly IFooFactory _fooFactory;
         private readonly string _param;
    
         public Consumer(IFooFactory fooFactory, string param)
         {
             _fooFactory = fooFactory;
             _param = param;
         }
    
         public void PerformAction()
         {
             Foo foo = _fooFactory.Construct(_param);
             // Additional processing of foo
         }
    }
    
    public interface IFooFactory
    {
        Foo Construct(string param);
    }
    
    public class MyNinjectModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IConsumerService>()
                .To<ConsumerService>()
                .WithConstructorArgument("param", /* Some run time param */);
            Bind<IFooFactory>().To<FooFactory>();
        }
    }
    
  • Rely on Ninject to inject the value constructed by the IFooFactory into Consumer directly

    public class Consumer
    {
         private readonly Foo _foo;
    
         public Consumer(Foo foo)
         {
             _foo = foo;
         }
    
         public void PerformAction()
         {
             // Additional processing of foo
         }
    }
    
    public interface IFooFactory
    {
        Foo Construct(string param);
    }
    
    public class MyNinjectModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IConsumerService>()
                .To<ConsumerService>()
                .WithConstructorArgument("foo", 
                                         ctx => ctx.Kernel
                                                   .Get<IFooFactory>()
                                                   .Construct(/* Some run time param */);
        }
    }
    

Should I favour one over the other?

Community
  • 1
  • 1
rexcfnghk
  • 14,435
  • 1
  • 30
  • 57
  • There's not much to it, but the latter is simpler in the consuming class, so I would go for that. – stuartd Sep 07 '16 at 09:18
  • 1
    @stuartd The second version seems much easier to understand (without the Ninject bindings) and unit test too. – rexcfnghk Sep 07 '16 at 09:19

0 Answers0