I am reading currently "Dependency Injection in .NET" by Mark Seemann. And I am wondering what would be the best way to compose a DDD ASP.NET MVC application.
In simplified scenario, the general rule of thumb, would be to have Domain Model which would be core of the application, and would not have any dependencies on Data Layer or Presentation. It would expose certain interfaces which Presentation would use (hence dependency) and Data Layer would implement (hence dependency). So it is all nice and clear.
However, now, when we compose the application. Which in case of ASP.NET MVC app we would do in global.asax (http://blog.ploeh.dk/2011/07/28/CompositionRoot). Our composition root will require dependency on all layers, because it needs to register all applicable types.
This makes all dependencies looks messy, now Presentation layer has a project reference to Data Access layer (in VS terms). It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers.
Is there a clean way to solve this conundrum? It almost would be nice to have the Composition Root outside of the presentation layer, but in MVC that would not be possible.
UPDATE
After asking this question I found a related one: DAL -> BLL <- GUI + composition root. How to setup DI-bindings? and it had some interesing solutions. The accepted solution is almost perfect, however I would like the composition root to be outside of presentation layer, and reference presentation layer rather than the other way.
One reason for that is that it is to me more conceptually clear - composition should be on the very top. The other reason is that in my case presentation layer has many DI objects in it already (mostly domain object to view model mappers) and I would like to have them composed in one spot as well.
This thread gave me some ideas though, I think what I am trying to do may be possible.
It is easy for a developer to make a mistake and use types form Data Access layer directly, which would effectively couple those layers.
It's easy to do a lot of stupid things no matter how you try to prevent it. Don't model your application after what the developer may not do. Model it so it's easy to do things correctly.
he accepted solution is almost perfect, however I would like the composition root to be outside of presentation layer, and reference presentation layer rather than the other way.
My container has support for what you ask. In each project create a single module which registers everything else:
public class CompositionRoot : IContainerModule
{
public void Register(IContainerRegistrar registrar)
{
registrar.RegisterType<ISomeType, SomeType>();
}
}
In your UI project you simply load all dlls:
registrar.RegisterModules(Lifetime.Scoped,
Environment.CurrentDirectory,
"myproject.*.dll");
That's it (you can also replace most manual RegisterType etc with a single line if you tag your implementations with the [Component]
attribute).
https://github.com/jgauffin/griffin.container
Most IoC containers expose the concept of logically grouping together bindings into a module.
The effect is that only the assembly containing the module needs to know about the concrete implementations, and the composition root only needs to access the modules.
Example (pseudo):
// In data access assembly
namespace MyProject.DataAccessLayer
{
internal class MyRepository : IMyRepository
{
// ...
}
public class DataAccessModule : IModule
{
void Configure(container)
{
container.ForInterface<IMyRepository>()
.UseType<MyReposutiry>()
.Singleton();
}
}
}
// In presentation layer assembly
namespace MyWebApp
{
void Booptstrap()
{
var iocContainer = /* ... */
iocContainer.AddModule(new RepositoryModule());
}
}
Notice that the concrete implementation class of MyRepository is internal. Only the module needs to see it.
The natural extension to this pattern is that each assembly exposes only an IoC module publically, all the other concrete classes are an internal implementation detail.
One way to attain a greater degree of encapsulation is to expose the domain as an HTTP service, with say ASP.NET WebAPI. The ASP.NET MVC solution would then reference this API. There would be no data access dependencies, only a reference to the service. For simplicity, the published language of the API can be extracted into an assembly that could be referenced by the MVC presentation solution. The trade-off of this approach is added moving parts and the steps involved in creating and managing a service.
Additionally, having the configuration you describe is perfectly acceptable. The encapsulation attained by extracting a service might not be worth the price. Developers should have the discipline to prevent leaks of the sort you describe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With