Microsoft.Framework.DependencyInjection: Adding services inside a scope - dependency-injection

I started looking into Microsoft.Framework.DependencyInjection / Microsoft.Extensions.DependencyInjection (renamed post-beta 8) for usage in my own framework based on the MVC-paradigm.
For this I per request have 3 scoped levels in which I'm trying to use the new Microsoft DI. A shared root scope for my the entire application, a nested scope for every controller and a further nested scope for every view.
Even though this scoping works for resolving services from the root, I have no idea on how to inject services into the lower scopes. I want to be able to inject specific services for my controllers/views per request which are used during the lifetime of the request and then discarded.
The possibilities I've explored are IServiceScopeFactory and CreateScope, but that only gives me a read-only IServiceProvider. Other than that there's AddScoped but that just returns the original ServiceCollection.
Am still looking for a way to create the root containers, register its services for the entire application and then the ability to create a scope and register scoped only available in that scope (and its parents).
Any ideas on how to achieve this? The documentation for the Microsoft DI is scarce so far.

Related

How do you avoid injecting global state when sharing dependencies in DI?

Imagine you inject a single database connection to a handful of service classes. They now share what's essentially a global mutable state. How do DI frameworks deal with this? Do they:
Freeze the dependency before injection?
Only share immutable objects?
Wrap each dependency in a decorator to only provide exactly what's dependent on?
I tried searching for this and am a bit surprised I didn't find much. Feel free to provide links.
Related: https://en.wikipedia.org/wiki/Principle_of_least_privilege
Most DI containers provide the feature of registering a dependency within a Lifetime. For instance in .net core DI you can register a service with three different lifetimes:
Singleton: There is only one single instance. All the consumers of that service will use that instance. If one consumer changes the state of that dependency, all the other consumers will see that change.
Scoped: There is one instance per scope, where a scope is a web request. If a consumer changes the state of a scoped service, all the other consumers that will run in the same web request will see the change.
Transient: Each consumer uses a different instance of the service.
Always in .net core, the DBContext is (by default) added as a scoped service, this means that in the same web request all the consumers will use the same instance and this is useful when you need to run a transaction across different consumers (or better across different repositories).

Grails 3 change default service scope

In grails 3, the default service scope is Singleton, the documents show it's easy to override this by defining
static scope='request'
in the service class. Is it possible to change the default service scope for an application similar to the way it is done for controllers in application.groovy?
The specific issue is a Service class in a plugin is calling application services (which are designed around request scope). This was working in grails 2, but with the upgrade to grails 3 it no longer does.
Is it possible to change the default scope for an application similar
to the way it is done for controllers in application.groovy?
There is no direct support for that, no. You could write a bean definition post processor that could impose that change.

Downside of using my own Autofac LifetimeScope in MVC application

I am writing MVC UI wrapper reusing legacy core libraries that were written down for desktop edition using Autofac for DI. The problem I am facing is, core libraries are working with Lifetime scope that I can't change while MVC requires InstancePerRequest.
So what happens is, in MVC, if I register my services for InstancePerRequest scope, they get disposed by core libraries before request completes. It makes MVC application unhappy.
I tried using LifeTimeScope for all services in MVC app too. Since Lifetime scope is shorter than Request life, it appears to work in MVC.
Is there any downside in this approach?
Note: In legacy code all the time services are being resolved manually, instead of being injected through constructor. Like:
using (var scope = IocContainer.BeginLifetimeScope())
{
var service = scope.Resolve<IMyService>();
return service.FindAll();
}
MVC will work with InstancePerLifetimeScope for services as noted in the documentation about sharing registrations across apps that have and apps that don't have request scopes.
I think there are going to be potentially two gotchas in your approach to creating your own lifetime scope. Whether you can live with them is very much app specific so you'll have to judge for yourself.
Problem 1: Early Disposal
In your example you show a factory or service IMyService being resolved, doing some work, and returning that work. At the end of the using statement the owning lifetime scope is getting disposed. That means IMyService will be disposed (if it's IDisposable) and any dependencies that IMyService requires will also be disposed. In the case of things like database contexts or connections, that well could mean the return value becomes invalid because you won't be able to update the values or read additional data against a disposed connection.
Problem 2: Singleton/Sharing Issues
Lifetime scopes are sometimes used to isolate units of work or sets of components that need shared context. For example, in MVC you only have one instance of the controller for the whole request - no matter how many times you resolve the controller object, for that request it'll be the same instance. You might see a similar thing with database connections - one connection from the pool allocated for an entire request lifetime.
By creating your own lifetime scope you are also creating a sort of logical unit of work. Any dependencies for IMyService will not be shared with the rest of the MVC request. In fact, it's more like that tiny lifetime scope is its own request or its own unit of work. No overlap.
General Resolution
As noted in the doc I linked to earlier, register things as InstancePerLifetimeScope if they need to be used in both MVC and non-MVC contexts and just let the MVC request semantics handle spinning up and disposal of scopes if possible.
If that won't work, it'll be up to you and your app code to figure out if you can live with the issues here or if you need to address them. If you need to address them, that, too, will be app specific so there isn't "guidance" to provide - you're on your own for that.

ASP.NET MVC dependency injection outside the controller with Unity

I am building an ASP.NET MVC 5 application using the repository and service layer design patterns. I have used unity to inject my services into my controllers.
This works nicely and until now I have not had a need to consider instantiating any objects requiring injection of interfaces outside my controllers. However I have a need for this when configuring my application startup to setup some users in the database.
For this I wanted to user my UsersService that I've built. And it occurred to me as the application grows there will surely be other occasions when I'll want to do the same, such as calling a service from within another service.
I see that I can instantiate a Unity container and call resolve on it to get my new instance of a service:
IProductService productService = container.Resolve<IProductService>();
However this kinda smells to me, having the container leaked all over my application seems like an anti pattern. So is there a better way to do this?
Unity and other dependency injection containers automatically do this. When you inject a service into a controller, it will automatically resolve the entire dependency graph of that service. Not only can you resolve dependencies of the service and its dependencies, you should inject dependencies into the service that needs them instead of the controller.
Any class (including the controller) that has more than a handful of dependencies is a code smell that you are violating the Single Responsibility Principle, and you most likely should refactor to aggregate services.
And yes, injecting the container to any point outside of the composition root is an anti-pattern called a service locator.
As for injecting services outside of the controller, it is important to distinguish between injectables and runtime data. For example, some try to inject services into DTO objects, attributes, static classes/extension methods, and other places where it is anti-pattern for services to be injected. For these situations, it is important to properly assess the situation and refactor toward a DI-friendly solution - favoring constructor injection over other alternatives and considering a service locator as a last resort. For example, if you are trying to make an extension method with a dependent service, most likely you have some functionality that itself should be a non-static service, DTOs should never be created from a DI container, and you may have to make use of more than one extension point in MVC where you inject the container within the composition root of the application, which does not constitute a service locator.
Is it worth it? Usually. What is gained? You gain the ability to change the application much more quickly than if you have a tightly-coupled application in ways that the designer of the application may not have even anticipated. So the extra cost of ensuring the application is loosely-coupled is usually more than recouped in ongoing maintenance of the project. As a side benefit, you gain the ability to easily unit-test each component independent of the others.

Proper SimpleInjector configuration for WebApi and UnitOfWork Pattern

I have read through the SimpleInjector documentation a few times. But have a few questions.
Context:
3 tier app (presentation (mvc + api controllers), service (business logic), data (repositories, entities, etc)
Unit of Work is a thin wrapper around EF's DbContext
my DbContext and Unit of Work are registered PerWebRequest, using
RegisterWebApiRequest causes an exception, because the Unit of Work is used
outside of Web API requests.
my MVC and Api controllers registered using RegisterWebApiControllers(GlobalConfiguration.Configuration) and RegisterMvcControllers(Assembly.GetExecutingAssembly())
Each controller has one or more services injected into it.
Each service has one or more repositories injected into it.
A service may also have another service injected into it.
I want the same Unit Of Work/DbContext to exist in all my services/repositories.
Questions:
Because I am using services in my MVC controllers as well as API controllers; does that mean I can not use RegisterWebApiRequest in place of RegisterPerWebRequest?
none of my services, repositories, etc, maintain any state, I would get the same functionality using PerWebRequest as Transient; is there any advantage to using PerWebRequest over Transient?
Please read the following q/a: How to configure simple injector container and lifestylse in a MVC web app with WebAPI, WCF, SignalR and Background Tasks. The answer explains that:
Putting your Web API in the same project as your MVC controllers is a bad idea from an architectural perspective.
But if you want to do this, you can use the WebRequestLifestyle in both type of applications. The WebApiRequestLifestyle is meant as lifestyle that works for Web API for both IIS and self-hosted environments, but since you placed the Web API controllers in the same project, you are clearly only interested in IIS-hosted; in that case the WebRequestLifestyle will do just fine.
Because I am using services in my MVC controllers as well as API controllers; does that mean I can not use RegisterWebApiRequest in place of RegisterPerWebRequest?
Both lifestyles use a different way of caching. The WebRequestLifestyle uses the HttpContext.Current.Items dictionary to store its SimpleInjector.Scope instance, while the WebApiRequestLifestyle uses the CallContext class to store the Scope during the lifetime of a single asynchronous operation.
Just as the WebRequestLifestyle can be used while resolving Web API controllers, you can use the WebApiRequestLifestyle (or the underlying ExecutionContextScopeLifestyle) for MVC controllers as well. But if you want this, you will create your own IDependencyResolver implementation for MVC that will explicitly start and end an ExecutionContextScope. The absense of a Scope stored in the CallContext is the reason resolving MVC controllers fails when registering services using the WebApiRequestLifestyle. But while it's possible to use the WebApiRequestLifestyle in MVC, the otherway around is much easier, since no custom code is required.
none of my services, repositories, etc, maintain any state, I would get the same functionality using PerWebRequest as Transient; is there any advantage to using PerWebRequest over Transient?
If services don't have state, it doesn't matter what lifestyle they have. The only restriction is that they have dependencies that have a lifestyle that is equal to or longer than their own. Violating this restriction is called Captive Dependencies and can cause all kinds of trouble. Because captive dependencies are bad, Simple Injector v3 checks and prevents this for you.
Although you can probably make all objects in your configuration scoped (non-transient), making them transient is usually easier to configure, and might result in better performance (although you will probably never notice the difference in real life).

Resources