2

I have been reading a lot of sample code for DI and autofac. One thing I noticed was that many people bundle the interfaces and implementations in the same project. From design point, I believe this is not correct and all interfaces should be in separate assembly. So I define my projects like this:

UI - Web App/Windows App/Both - Views - Models - Controllers/ ViewModels Business - Services/Processes - Interfaces - Model DataAccess - Repositories & UoW - Interfaces - Model

This way, my business services refer only to DataAccess interfaces and models but stay independent of actual implementation. Same way, the UI also refers to only business interfaces and model and there is clear separation. This also helps me in testing where I can independently test the layer.

My question is for Autofac Module declaration. I need to set up my build to copy the implementations into final deployment directory. My business modules need to refer to data access implementation and UI needs to access business modules.

  1. How should I handle this chain of dependencies in modules?
  2. Where should I place the module classes and how should startup code discover all the modules in easiest possible manner?

I am considering Autofac's assembly scanning but not sure if that is only option. Also note that I am already following naming convention and in most cases, I am not going to write individual bindings. My concern here is that

  1. since the projects referencing interfaces are unaware of implementations, I cannot write any specific bindings in the calling assembly such as the UI root assembly.
  2. Some sources talk about keeping the assemblies clean of any DI implementations and having separate assemblies for modules. Is that a good approach for all types of applications? (E.g. enterprise LOB app or Web App vs and ISV desktop app distributed to many independent users)
Hemant
  • 411
  • 4
  • 15

1 Answers1

1

My opinion is that having interfaces and implementations in separate assemblies is overdoing it and doesn't provide value, because you'll have to deploy both assemblies for your project to work. I like to refer to this tweet from Paul Stovell where he states that namespaces are units of concerns whereas assemblies are units of deployment. I find this resonates a lot with me.

Back to your question: at the end of the day, your executable project (web app or Windows app) needs to know be aware of both the interfaces and the implementations.
My opninion is that the Autofac modules should live in the top-level project, hence it should have references to all the necessary projects. My reasoning behind this is that in addition to defining the service registrations, you'll also define the lifetime for each of them. That notion is dependent on the project that uses your dependencies; a web project might have somes services registered per HTTP request while a Windows app could have different lifetimes.

To me, modules are a great to group registrations together, but it doesn't mean they need to live in the same project as the services it contains registrations for.

Mickaël Derriey
  • 12,796
  • 1
  • 53
  • 57
  • One of my concerns was testing as well. I like to define interfaces first and implementations later. So when the downstream implementations are not complete, I can still run the tests. This is helped by separate assemblies. I like your point about module location. My concern with this approach was additional references I would need in top level project. This may cause inadvertant use of lower assemblies. Would you recommend a bootstrap assembly in such case? – Hemant Dec 19 '18 at 07:26
  • I don't see how having interfaces and implementations in separate assemblies helps with testing; whether an assembly contains only the interface definition or both the interface and the implementation shouldn't impact testing. What is a bootstrap assembly? I wouldn't worry about references in the top-level project. The lower-level assemblies will end up in the top-level project output directory anyway due to the dependency chain. – Mickaël Derriey Dec 20 '18 at 02:52