What is cross wiring? Cross wiring, in relation to Simple Injector and dependency injection, is the ability for Simple Injector’s dependency container to resolve services and dependencies from .NET Core’s built in configuration system.
Service collection
In our previous post with DI, DI with .NET 5, we discussed how dependency injection is built into the .NET Core’s framework and how services can be registered using the default built in container. This is done through the service collection and .NET core registers its built in framework components with the service colleciton in the Startup.cs
class.
Because of how integrated the service collection is with .NET core, replacing the default container with Simple Injector’s container is not the recommended way of using Simple Injector. Instead, Simple Injector will use a technique called cross-wiring
where it will try to first resolve services from its own container, and if the service cannot be resolved, it will use the service collection and .NET Core’s default container. Hence, this will allow any services registered through the service collection to be resolved using Simple Injector’s container. This is done by attaching an event to Simple Injector’s ResolveUnregisteredType
event.
While we’ll be able to resolve services registered through the service collection from the container, this is one way and we will not be able to resolve services registered through the container.
Note: It is still recommended that services are registered through the container and not through the service collection. This will ensure that the container is able to resolve services right away instead of looking at the service collection after it is not able resolve the dependency. All application based dependencies should be registered through the container and we should only leave framework level dependencies in the service collection.
Working with scopes in HTTP requests
One thing that needs to be noted when working with cross wiring is that services resolved through cross-wiring
will resolve the service with the lifestyle registered through the framework. In the scope of an HTTP request, Simple Injector will resolve services and reuse the .NET Core’s request scope. So if there are multiple simple injector async scoped lifestyles within the same http request trying to resolve a scoped service reigstered through the service collection, the same instance will be returned.
// Register service through the service collection
services.AddScoped<IMathService, MathService>();
// In a controller
[HttpGet]
public string Get() {
using (AsyncScopedLifestyle.Begin(_container)) {
var service = _container.GetInstance<IMathService>();
Debug.Writelin(service.GetHashCode());
}
using (AsyncScopedLifestyle.Begin(_container)) {
var service2 = _container.GetInstance<IMathService>();
Debug.Writelin(service2.GetHashCode());
}
}
In the above example, service1
and service2
will point to the same instance.
References
[Simple injector documentation] (https://docs.simpleinjector.org/en/latest/servicecollectionintegration.html) [Cross wiring injections and same instance] (https://github.com/simpleinjector/SimpleInjector/issues/796)