1

I am using IoC container to register and resolve types.

I have the following Projects:

ProjectA

ClassA - SubClass1 - SubClass2

ProjectB(Class Library)

ClassB - SubClass3 - SubClass4

ProjcetA is using ProjectB.

ProjectA is the entry point to the application.

ProjectA doesn´t know about SubClasses3 and SubClass4.

I have separate unit test projects for ProjectA and ProjectB.

Since I don´t want ProjectA to know about SubClasses3 and 4 what is the proper way to register types in the class libary?

Should I pass the IoC container from ProjectA to B or use two IoC containers?

My question is not how to make library DI agnostic/non-di usable. My question is what is best practices when registering child dependencies in a class library.

4
  • What IoC container are you using? Commented Feb 14, 2018 at 16:12
  • But if you pass unity container from ProjectA to ProjectB then automatically know about SubClass3 and SubClass4... Commented Feb 14, 2018 at 16:13
  • Hi @JuanR, AutoFac, but I did abstract it to my own librarí since I don´t want to depend on the vendor Commented Feb 14, 2018 at 16:13
  • Hi @Lepijohnny, yes I could pass the container from ProjectA to ProjectB. But since ProjectB doesn´t have an entry point, should I create a special method for passing the container in and registering subclass 3 and 4? Commented Feb 14, 2018 at 16:15

2 Answers 2

1

Project B shouldn't need to know anything about your IoC container. If you take that approach soon all your DLLs depend on some specific IoC library.

In Autofac you can do something like this:

        builder.RegisterAssemblyTypes(typeof(ClassB).Assembly)
            .Where(x => typeof (ISomeInterface).IsAssignableFrom(x))
            .AsImplementedInterfaces();

Here I'm registering everything that implements a specific interface from another DLL. I have NO direct dependencies on any classes in that assembly and they are declared as internal to enforce that. For unit testing my test project uses [InternalsVisibleTo] in order to instantiate the classes directly but without exposing them as public.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi, how does ISomeInterface know what implementation to use?
I see it picks the only implemented interface?
@doorman AsImplementedInterfaces registers those classes as all of their implemented interfaces. e.g. IBackgroundService might inherit from ISomeInterface and IEmailService too. Now my app can ask for an IEmailService and get one but I don't need to register all of the separate interfaces. You can register them separately if you wish.
If Assembly B needs to do more complex registration work using the ContainerBuilder you can use an Autofac Module to at least encapsulate all of that registration in one place and to simplify the initialization code back in the main assembly.
1

My question is what is best practices when registering child dependencies in a class library.

I don´t want ProjectA to know about SubClasses3 and 4

See Ioc/DI - Why do I have to reference all layers/assemblies in entry application?.

If you follow the DI pattern, there will be no "child dependencies" of your class library. Instead, the dependencies will completely (except for maybe some abstraction libraries) be reduced to a 1 to 1 relationship with your composition root in the startup application.

It is ideal for your ProjectA application to depend on SubClasses 3 and 4. If SubClasses 3 and 4 depend on one another or components from other libraries, you drag extra dependencies along when you use SubClass 3 or SubClass 4.

Instead, put all of the coupling code in your composition root and no coupling code inside your application layer class libraries. This puts the application in charge of all of its dependencies.

If you have other types of class libraries, such as reusable application components, there are techniques that can be used to couple them but allow them to still be injectable. See DI-Friendly Library and DI-Friendly Framework.

NOTE: Putting all of the coupling code in your composition root doesn't necessarily mean you have to put it all in the same method or class. You can organize it across several classes and/or use conventions as in Ian's answer to make it maintainable. But at the end of the day, the application should be in charge of its dependencies, so you shouldn't move this code into other application layers - keep it in the startup layer of the application.

3 Comments

Thanks @NightOwl888 ... but still it seems a bit dirty to me that ProjectA needs to know the implementation of ProjectB . I don't want ProjectA to know about the underlying mechanism of ProjectB. I think this could be achieved simply by passing in the container to ProjectB as a parameter and regeistering SubClass 3 and 4 in there. Furthermore for the ProjectB unit tests where ProjectA doesn't exists how would you register the classes, within the unit test itself?
What type of library is ProjectB? Is it an application layer, plugin, component library, or framework? If one of the latter 2, see the above linked posts. It is possible to create a fluent builder to allow for substitution of components while still making it possible to wire it together in one call.
It's just a class library containing business logic used by a webservice

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.