问题
I've spent a lot of time reading these articles (along with many others):
Mark Seemann - Pure DI
Mark Seemann - When to use a DI Container
Mark Seemann - Compose object graphs with confidence
Mark Seemann - Don't call the container; it'll call you
Mark Seemann - Understanding the Composition Root
and I'm still trying to wrap my head around DI and the concept of "wiring up the dependencies" and the "auto wiring" functionality of an IoC container.
I think I understand the theory of Dependency Injection and Inversion of Control and I've implemented the example shown here from 2016 (I updated the code to use PSR-11 and eliminate the need for the container-interop
package):
- https://www.sitepoint.com/how-to-build-your-own-dependency-injection-container/
The application of the container example is shown at the GitHub link: https://github.com/sitepoint-editors/Container .
Note that while this example uses PHP, I'm trying to understand the details of DI independently from language, so any language is welcome.
Can someone explain the difference between manually wiring up dependencies, and using a container's auto wiring functionality? The SitePoint article briefly mentions that more advanced containers add the automatic wiring functionality, implying that the example doesn't contain this function already. Can someone explain the application shown on the GitHub page and how that relates to core DI and IoC concepts, like the Composition Root.
回答1:
Can someone explain the difference between manually wiring up dependencies, and using a container's auto wiring functionality?
Pure DI is the practice of applying DI without using a DI Container. This means that you build a graph of objects by newing up objects using the new
construct of your programming language. See for instance this example in C# (from listing 12.2 of Mark's book Dependency Injection Principles, Practices, and Patterns):
new HomeController(
new ProductService(
new SqlProductRepository(
new CommerceContext(connectionString)),
new AspNetUserContextAdapter()));
According to that book, Auto-Wiring is:
the ability to automatically compose an object graph from maps between Abstractions and concrete types by making use of type information supplied by the compiler and the [runtime environment]. (see 12.1.2)
In other words, with a DI Container, you will be able to 'just' tell the container about your types, and it will figure out which dependencies a type has and will be able to 'wire' that type with its dependencies.
Considering the previous example, listing 12.3 shows how you only have to specify the mappings between abstractions and concrete types in a container:
var container = new AutoWireContainer();
container.Register(typeof(IUserContext), typeof(AspNetUserContextAdapter));
container.Register(typeof(IProductRepository), typeof(SqlProductRepository));
container.Register(typeof(IProductService), typeof(ProductService));
container.Register(typeof(CommerceContext), () => new CommerceContext(connectionString));
And when you ask for a HomeController
, the container knows how to construct the entire graph.
The SitePoint article briefly mentions that more advanced containers add the automatic wiring functionality
To me, Auto-Wiring is what makes a library into a DI Container. Something can't be called a DI Container if it doesn't, at the very least, support Auto-Wiring.
来源:https://stackoverflow.com/questions/59759128/dependency-injection-composition-root-and-entry-points