1
votes

I have a general framework which contains a lot of assemblies, some are common, some are designed for Server applications, and some for Client applications (Each feature has a base-line library while any application-type-specific extensions are defined in a different assembly).

I'm trying to decide where in my framework I should declare Autofac registration modules for the different modules I create.

My code is completely decoupled and the IoC container is not used intrusively at all within my code. Also, other external dependencies (such as serializers, API assemblies, etc...) are referenced only by the modules that expose them to the framework. That causes some assembly-bloating issues because I have (for example) an entire assembly that adapts JSON serialization into my serialization interfaces (hiding it from the rest of my application code).

I thought about several possible solutions:

  1. Adding an assembly to adapt with Autofac Modules on top of every "module-exposing" assembly.

    • The main advantage is that every assembly will export its modules and all its the "functionalities" will be straight forward available in a modular fashion.
    • The main disadvantage is that it probably will double the amount of assemblies I have.
  2. Add only several Autofac-aware assemblies that will define different modules (Obviously not randomly), maybe one for containing the modules used for a specific application.

    • This solution adds much less excessive assemblies, but is less modular, and causes possibly unwanted dependencies between all the assemblies in the group. Also if modules are created for a specific application repository, there is module reusability only within that repository (and no shared modules between different applications).
  3. Create my own module registration "contract" interfaces within my framework and create a contract-consumer for the actual IoC container I'm using in order to adapt.

    • The advantage is that every assembly can contain modules without any dependency (assuming the registration interfaces are in my most basic library). The disadvantage is that solution obviously limits the things I can do (similar to the "inner-platform" effect).

Are there any alternatives I'm missing? Are there more advantages/disadvantages that I fail to see? Did anybody experience anything similar dilemmas and the practices they've applied?

Thanks a lot!

1

1 Answers

0
votes

I don't know if you still need a suggestion about this question, but I'll try to give an answer, because the topic is really interesting.

The question is: do you plan to use another IOC framework? Or simply you would like to be super-flexible? I suspect the latter and, if that's the case, I would say YAGNI: keep your Modules in the same assemblies, and keep the assembly count down to the minimum. If you're not going to use nuget to distribute the assemblies (and even if you are) you will appreciate having to cope with less clutter.

If you plan to use another IOC, than, by all means, keep your modules outside of the assemblies. But I would try to commit to a single DI framework as much as I can: it is simple to switch later (it's purpose is exactly to keep the dependency count to a minimum) and you will see much more clearly what's the best approach for the refactoring. Still, you will need to keep in mind not to take dependencies upon ILifetimeScope, but given your question you probably are already doing that.

As a side note, the approach I use is as follows:

  • common framework assemblies, containing Factory-like classes that will use Autofac to do the heavy lifting of object creation and initialization (e.g. a custom ControllerFactory in an MVC site or such): you need a reference to Autofac. So, I would put a Module into the same assembly, so the factory class, which is coupled to Autofac anyway, is in the same place. Less assemblies => less clutter => easier to read and mantain.
  • assemblies containing POCO classes or such, largely unaware of Autofac, like, for example, Model classes or Service layer implementation classes. Here, there should never be the necessity of an explicit Autofac scope or registration.
  • if I have some components which will need registration in Modules, I do not mind taking a dependency on Autofac just for the definition of the Module class. It's nice to have the simplicity of having components and modules sharing a common namespace structure and being in the same folder (or a conventionally based "Module" subfolder).

I don't know if any of this makes sense, drop me a line if you want some examples.