Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting an internal helper class while resolving a public class

I have the following architecture where a public Service class referencing an internal Helper class exists in another assembly:

ApplicationAssembly {
  public class Widget {
    public Widget(ReferencedAssembly.Service service) { ... }
  }
}

ReferencedAssembly {
  public class Service {
    public Service(Helper helper) { ... }
  }
  class Helper { ... }
}

(I realize that I can't put an internal class in the arguments of a public class's constructor--I'm just trying to illustrate the IoC pattern I'm going after.)

The problem is that ApplicationAssembly can't see ReferencedAssembly.Helper, so it can't be registered in my IoC container (Autofac in this case). As a result, Helper cannot be resolved when I try to resolve Service. What is my best option here?

  • Option 1: Remove Helper from Service's constructor and new it up in the constructor explicitly. I don't like this option because it kind of breaks the IoC paradigm.

  • Option 2: Make Helper implement a public IHelper interface, then add a public module within ReferencedAssembly that registers Helper as an IHelper. I don't like this option because it requires ApplicationAssembly to know too many implementation details about Service, and if the user forgets to register that module at startup everything breaks.

  • Option 3: Create a public static constructor on Service that builds a 2nd IoC container specifically for ReferencedAssembly and registers Helper in it. Remove Helper from Service's constructor and resolve it within the constructor using the 2nd IoC container. This seems like my best option but requires more "plumbing" code than the others. I'm also not a big fan of public static constructors.

  • Option 4. Change my architecture to something else altogether.

like image 939
Mike Avatar asked Jan 23 '11 17:01

Mike


People also ask

How dependency injection works internally in c#?

Using dependency injection, we modify the constructor of Runner to accept an interface ILogger, instead of a concrete object. We change the Logger class to implement ILogger. This allows us to pass an instance of the Logger class to the Runner's constructor.

Why should we use dependency injection c#?

The intent of Dependency Injection is to make code maintainable. Dependency Injection helps to reduce the tight coupling among software components. Dependency Injection reduces the hard-coded dependencies among your classes by injecting those dependencies at run time instead of design time technically.

Why do we need dependency injection?

The dependency injection technique enables you to improve this even further. It provides a way to separate the creation of an object from its usage. By doing that, you can replace a dependency without changing any code and it also reduces the boilerplate code in your business logic.

What is a. net dependency DI or IoC Container?

IoC Container: also known as Dependency Injection (DI) Container, it is a programming framework that provides you with an automatic Dependency Injection of your components.


1 Answers

The way to register internal types with Autofac is to include an Autofac Module inside the assembly with the internal types, and register the module with the container. Because the module is in the same assembly it can configure the ContainerBuilder with the internal types.

I think the best option is to make Service implement a public interface, then make the Service class that you have currently internal. Autofac will happily instantiate an internal class to provide a public interface.

The other option (to allow Service to take a constructor dependency on an internal type) is to make Service's constructor internal, and then use a constructor finder in the Service type registration:

builder.RegisterType<Service>()
  .FindConstructorsWith(new BindingFlagsConstructorFinder(BindingFlags.NonPublic));
like image 50
Nicholas Blumhardt Avatar answered Oct 05 '22 21:10

Nicholas Blumhardt