简体   繁体   中英

Modern Layered Architecture Implementation

I recently finished reading Dino Esposito's great book Modern Web Development , and in it he addresses a suggestion for a Domain Driven Layered Architecture for web applications. I have always struggled with a specific piece of suggestions I have seen similar to the one below: 在此处输入图片说明

Specifically with reference to the IoC being made in the Infrastructure layer. I understand the reasoning behind this and it makes sense to me however how do you adequately implement that within the bounds of the ASP.NET MVC framework? To add a dependency resolver you need to implement the IDependencyResolver interface which exists in the System.Web.MVC namespace.

In past projects I would typically implement my IoC within the MVC application itself in the startup folder however this seems to be at odds with the suggestion for the layout.

I do not want to turn this into an opinion type of question, all I am looking for is a possible, actual concrete way to implement this pattern without dragging the System.Web.MVC namespace down to the infrastructure layer.

EDIT

To add a follow on diagram for the suggested architecture, and the part that is still confusing to me, it would appear that Dino's suggestion does indeed put the IoC container in the infrastructure assembly:

盒子是组装

Answer to Your Question

Fundamentally, your question is "I am looking for is a possible, actual concrete way to implement this pattern without dragging the System.Web.MVC namespace down to the infrastructure layer"

There is a way to do this, and it involves introducing a new IoC container library, one dedicated for the purpose.

IDependencyResolver does not have to be your system wide resolution interface - it is just the interface used by MvC. There are other IoC containers, and a number of them provide adaptors to inject an implementation of IDependencyResolver that wraps their IoC logic.

This permits a few things:

  1. The MvC components that depend on the ability to perform an explicit resolution can still depend on IDependencyResolver
  2. Other layers in the system can depend on a different resolution interface, and thus contain a reference to an isolated fit-for-purpose assembly
  3. Both the MvC layer and the other layers will all be accessing the same set of dependency/implementation registrations

Some examples of IoC containers that support this:

  • Autofac - with Autofac Mvc Support

    • You can see the last line of the sample is:

       DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
    • After that line, any MvC component that depends on IDependencyResolver will automatically get the AutofacDependencyResolver which wraps calls to the Autofac container

  • StructureMap - StructureMap.Mvc

Here is a comparison of a large number of c# IoC containers that may help you select the one that's right for you.

[Actual Implementation Concerns - aka My Opinion about Why this is NOT a good idea]

Your practice in your past projects of only using the IoC in the Mvc application is more correct, in my opinion, so the below concepts may already be familiar to you, but as you are considering referencing the IoC from the domain, I thought it worth exploring.

First question - Why?

While that answer provides a way to do what you're asking, based on that diagram, I confess it's not clear to me what the purpose is of depending on the IoC resolver from the domain layer, and why you would need to do that.

If you find yourself doing that, you may be accidentally using the Service Location Anti-Pattern

As outlined in that blog, there is no need to depend on the IoC resolver (or locator) - simply depend on the service you need, and let the IoC inject the appropriate implementation.

Part of the problem in understanding the intent is the diagram itself - it often happens that people draw diagrams by dropping on some boxes and connecting them up - without ever being clear about what the lines mean. Are they chains of dependency? Are they sequence of execution? What does it mean to have a line from the domain model box to the actual label of the infrastructure layer??? Is it depending on nothing? Or illustrative of a possible dependency that is not articulated here?

What should use the IoC resolver?

The only part of the system that should directly reference the IoC resolver is the composition root, which is effectively the entry point to the application. The first part 'wires up the object graph' - really, it registers how to resolve all possible dependencies from the interfaces that are depended on, to appropriate concrete implementations.

It then resolves the entry point object (or registers an IDependencyResolver so Mvc can resolve the entry point object, aka a controller). When the entry object is resolved, it automatically resolves all it's dependencies, in the process resolving next layer of dependencies, and so on all the way until you reach classes with no dependencies. Which is likely to be your domain layer, if you are doing DDD.

Dependency-less Domain Layer and the Onion Architecture

Since you are interested in DDD, the received wisdom is that the domain layer should not depend on anything that is not defined in the domain layer. If there is really a need to utilise the services of an infrastructure component such as a repository, use separated interfaces and put the interface in the domain layer, but the implementation in a concrete persistence layer.

The architectural pattern this lends itself to is known as the Onion Architecture also known as the Hexagonal Architecture

Using Other IoC Containers

While I don't think it's necessary to reference the IoC resolver/locator from the domain layer (or any layer, really), I do still think there is value in adopting a separate dedicated IoC container library, as outlined above.

The value is in some of the more flexible options for how to configure services, including some nifty convention based auto-configuration.

The one reason it might be worth depending on the IoC library in the domain layer is to co-locate the registration and configuration logic with the services that are being configured, which can help structure and organise your IoC dependency registrations. But just because you take a dependency on the IoC assembly to permit structuring your registrations, doesn't mean you should use the IoC resolver/locator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM