Register service with multiple lifetime - .net-core

In a .Net Core 2.2 application, I need a version of a service as transient and a version as scoped.
For a "regular" service, I could create two different interfaces, register one as transient and one as scoped, but if both need a DbContext, it would mean I'd need to create two DbContext (yes, one can just be a wrapper) and register both, but it feels improper.
I'm using dotnet Core's default Dependency Injection framework, which I'm not that familiar with. In UnityIoC, I could easily have done that using named registrations:
//Note: Pseudo-code
void Register(IUnityContainer container)
{
container.RegisterType<IMyInterface, MyClass>(
"Transient",
new TransientLifetimeManager()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>("Transient")));
container.RegisterType<IMyInterface, MyClass>(
"PerResolve",
new "PerResolve", new PerResolvedLifetimeManager()()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>(PerResolve)));
container.RegisterType<MyDbContext>("Transient", new TransientLifetimeManager());
container.RegisterType<MyDbContext, MyClass>("PerResolve", new PerResolvedLifetimeManager());
}
Bonus points: Using the IServiceProvider, how do I ask for the transient resolution vs the scoped resolution?

The simplest way to implement this is with two interfaces as shown in the following example:
interface IMyScopedInterface
{
void Foo();
}
interface IMyTransientInterface
{
void Foo();
}
class MyClass : IMyTransientInterface, IMyScopedInterface
{
public MyClass(MyDbContext dbContext)
{
}
public void Foo()
{
}
}
and then register your class using the following:
services.AddTransient<IMyTransientInterface, MyClass>();
services.AddScoped<IMyScopedInterface, MyClass>();
You don't need to do anything special with your DbContext in order to support this. Let's walk through how the DI system would resolve these services to see if it can clarify why that's the case.
To start, the DI system tries to obtain an instance of IMyScopedInterface (typically because the DI system is trying to instantiate some other service whose constructor takes an IMyScopedInterface parameter).
Because IMyScopedInterface has been registered with a scoped lifetime, the DI system first looks within it's collection of services that have already been instantiated for the current scope to see if it has already created an IMyScopedInterface. That search comes up empty handed, so the DI system then moves on to create a new instance of MyClass.
To do that, it examines MyClass's constructor and determines that it needs a MyDbContext, so it recurses back through this same flow in order to obtain a MyDbContext.
The DI system constructs an instance of MyClass supplying the obtained MyDbContext, and then caches this MyClass object as part of the current scope so that subsequent requests for IMyScopedInterface within the same scope can receive the shared object.
The same basic flow holds true for IMyTransientInterface except that the DI system doesn't bother looking for a previously instantiated instance of the object, and after constructing the new MyClass instance it doesn't cache it at all.
What should hopefully be clear from this flow is that it doesn't really matter what the lifetime of MyDbContext is. If it's registered as transient, then every new instance of MyClass will get it's own unique instance of MyDbContext. If MyDbContext's lifetime is scoped (which is the default behavior in Entity Framework), then all instances of MyClass created within a given scope will share a single instance of MyDbContext regardless of whether the MyClass instances were instantiated for IMyScopedInterface or IMyTransientInterface.

Related

What does it mean when saying "to be assigned something"| ASP.NET Core

I was reading a book about Learning ASP.NET Core API when I run to a part saying:
We create a private read-only field _repository that will be assigned
the injected MockCommandAPIRepo object in our constructor and used
throughout the rest of our code.
Here is some text I thought you'd better have:
Then there are some explanations related to the picture above:
Add the new using statement to reference ICommandAPIRepo.
We create a private read-only field _repository that will be assigned the injected MockCommandAPIRepo object in our constructor
and used throughout the rest of our code.
The Class constructor will be called when we want to make use of our Controller.
At the point when the constructor is called, the DI system will spring into action and inject the required dependency when we ask for
an instance of ICommandAPIRepo. This is Constructor Dependency
Injection.
We assign the injected dependency (in this case MockCommandAPIRepo) to our private field (see point 1).
And that’s pretty much it! We can then use _repository to make use of our
concrete implementation class, in this case MockCommandAPIRepo. As
I’ve stated earlier, we’ll reuse this pattern multiple times through
the rest of the tutorial; you’ll also see it everywhere in code in
other projects – take note.
Now, According to the highlighted part above in number 2, I got a little confused!
I've heard of "to be assigned by some value" before, but here, it is saying that:
that will be assigned the injected MockCommandAPIRepo object in our constructor
and as you see, there is no "by" added before the injected MockCommandAPIRepo object....
So, I have a question now. What does it mean by the highlighted part above in number 2?
Does it mean the same when we add "by" in the sentence? or not?
This is about dependency injection in Asp.Net Core. After we register service to the IOC Container, How to use it in our controller? We can inject them in controller via Constructor Injection. Once we register a service, the IoC container automatically performs constructor injection if a service type is included as a parameter in a constructor. In your question, An IoC container will automatically pass an instance of ICommandAPIRepo(MockCommandAPIRepo) to the constructor of CommandsController. Now we can use MockCommandAPIRepo in the constructor. But it can only be used in constructor, How can we use it in other method in CommandsController? Here we use:
private readonly ICommandAPIRepo _repository;
to create a global variable in CommandsController, Then in constructor, We use:
_repository = repository
assign the value of repository to _repository. Now _repository and repository has the same value, Because _repository is a global variable, So We can use _repository in other method in CommandsController. The whole process of dependency injection is done.

Injecting logger into middleware dependency

I have a middleware library I intend on using in multiple projects. The middleware itself looks something like:
public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk)
{
this.next = next;
this.logger = logger;
this.sdk = agentSdk;
this.sdk.Init();
...
}
Thanks to DI, I can simply inject my logger:
// Would rather this class be internal...
public class Sdk: ISdk
{
private ILogger<Sdk> logger;
public Sdk(ILogger<Sdk> logger)
{
this.logger = logger;
}
public void Init() {
this.logger.Info(...) // Do some logging
}
The downside to this is my class needs to be registered in every ASP.Net project's Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISdk, Sdk>();
Is the best/only route? Every time I want to inject a logger into a class, I need to register that class for DI in my composition root?
There is nothing wrong in having the consumer of your library compose the dependencies for this library in the composition root. That's how dependency injection works. You could of course provide some default implementations and a custom extension method that would register those default implementations into the DI and then let the consumer simply call your extension method.
There are a few things that I feel need clarification here:
Dependency injection/inversion of control
To understand what is the benefit of dependency injection(DI) it is better to look at the principle of inversion of control(IoT) that DI implements.
In your case you want SdkMiddleware class to contain a reference to ILogger implementation. The simplest way to do this is for SdkMiddleware class to create an instance of a class that implements ILogger interface. The downside of such approach is that SdkMiddleware needs to know which class implements ILogger interface and how to instantiate it. In other words, SdkMiddleware has control over the creation of ILogger object. The inversion of control happens when the responsibility of knowing which class implements ILogger and how to create an instance of it is taken away from SdkMiddleware to some other class (dependency container in DI) and the instance if it is given to SdkMiddleware to use (through injection in DI). In this case the control over the creation of ILogger object is outside of SdkMiddleware. Since this changes the direction of control, it is called "Inversion of control".
The benefit of this approach is when you will need to provide another implementation of ILogger or change the way you create an instance of that class, you don't need to change SdkMiddleware at all.
Bootstrapping
So now that we clarified why we are using DI, lets take a look at what do we need to actually use it.
The object that creates all instances, controls which object is injected into which and gives away ready to use objects is usually called DI container or IoT container. In asp.net core "IServiceCollection services" is used as such a container. But it still needs to know how to create objects and which implementation to inject for which interface. This is where bootstrapping comes in.
In a bootstrapper class or method you need to specify how objects are built from classes and how classes relate to interfaces. As an example of the former, imagine that you need to pass a connection string for a database from your configuration to a class that creates a db connection. As for the latter, that is exactly what your line "services.AddTransient()" does.
The answer
I am sorry it took so long to get to the actual answer for your question but I wanted to provide some overview first.
Do you need to specify a relation between a class and an interface to inject logger into your class? No. Your class may not even have an interface to begin with and DI container will inject all the dependencies in it by default if you ask for an object of a class instead of an instance of an interface. You can also use or define some convention over configuration solution so that binding of classes and interfaces will happen automatically.
The bottom line is that registration of a class and the actual injection are not connected. But the code you provided is the default way to do this.

Simple Injector LifetimeScope with DbContext

I am using simpleInjector 2.8.0.0 I would like to construct just one instance of a dbContext during a lifetime scope.
(My dependency chain has 2 dependencies on IDatabaseContext/DbContext)
I have a scope decorator which implements the lifetime scope (The scope decorator is being injected into a SignalRHub):
using (ServiceHost.Container.BeginLifetimeScope())
{
var commandHandler = ServiceHost.Container.GetInstance<ICommandHandler<TCommand>>();
//constructs 2 DbContexts.
commandHandler.Handle(command);
}
I have a lifetime scope registration for the IDatabaseContext:
container.RegisterLifetimeScope<IDatabaseContext, DatabaseContext>();
However, I can see (from a Guid) that I am creating 2 instances of the IDatabaseContext/DbContext within the scope.
Are you sure this is the same scope? Either you are nesting scopes, or you what you see is two actual request being handled. In the debugger, you might be able to view request information, for instance by inspecting the HttpContext.Current.Request.Url property.

Why would I want to use UnitOfWork with Repository Pattern?

I've seen a lot about UnitOfWork and Repo Pattern on the web but still don't have a clear understanding of why and when to use -- its somewhat confusing to me.
Considering I can make my repositories testable by using DI thru the use of an IoC as suggested in this post What are best practices for managing DataContext. I'm considering passing in a context as a dependency on my repository constructor then disposing of it like so?:
public interface ICustomObjectContext : IDisposable {}
public IRepository<T> // Not sure if I need to reference IDisposable here
public IMyRepository : IRepository<MyRepository> {}
public class MyRepository : IMyRepository
{
private readonly ICustomObjectContext _customObjectContext;
public MyRepository(ICustomObjectContext customObjectContext)
{
_customObjectContext = customObjectContext;
}
public void Dispose()
{
if (_customObjectContext != null)
{
_customObjectContext.Dispose();
}
}
...
}
My current understanding of using UnitOfWork with Repository Pattern, is to perform an operation across multiple repositories -- this behavior seems to contradict what #Ladislav Mrnka recommends for web applications:
For web applications use single context per request. For web services use single context per call. In WinForms or WPF application use single context per form or per presenter. There can be some special requirements which will not allow to use this approach but in most situation this is enough.
See the full answer here
If I understand him correctly the DataContext should be shortlived and used on a per request or presenter basis (seen this in other posts as well). In this case it would be appropriate for the repo to perform operations against the context since the scope is limited to the component using it -- right?
My repos are registered in the IoC as transient, so I should get a new one with each request. If that's correct, then I should be getting a new context (with code above) with each request as well and then disposing of it -- that said...Why would I use the UnitOfWork Pattern with the Repository Pattern if I'm following the convention above?
As far as I understand the Unit of Work pattern doesn't necessarily cover multiple contexts. It just encapsulates a single operation or -- well -- unit of work, similar to a transaction.
Creating your context basically starts a Unit of Work; calling DbContext.SaveChanges() finishes it.
I'd even go so far as to say that in its current implementation Entity Framework's DbContext / ObjectContext resembles both the repository pattern and the unit of work pattern.
I would use a simplified UoW if i wanted to push context's SaveChanges away from the repositories when they share the same instance of context across one web request.
I imagine you have sth like Save() method on your repositories that looks similiar to _customObjectContext.SaveChanges(). Now lets assume you have two methods containing business logic and using repos to persist changes in DB. For the sake of simplicity we'll call them MethodA and MethodB, both of them containing a fair amount of logic for performing some activities. MethodA is used separately in the system but also it is called by MethodB for some reason. What happens is MethodA saves changes on some repository and since we are still in the same request changes made in MethodB, before it called MethodA, will also be saved regardless of whether we want it or not. So in such case we unintentionally break the transaction inside MethodB and make the code harder to understand.
I hope i described this clear enough, it wasn't easy. Anyway other than that i cannot see why UoW would be helpful in your scenario. As Dennis Traub pointed quite correctly ObjectContext and DbContext are in fact an implementation of a UoW so you'd be probably reinventing the wheel while implementing it on your own.
The ObjectContext/DbContext is an implementation of the UnitOfWork pattern. It encapsulates several operations and makes sure they are submitted in one transaction to the database.
The only thing you are doing is wrapping it in your own class to make sure you're not depending on a specific implementation in the rest of your code.
In your case, the problem lies in the fact that your Context shouldn't be disposed of by your Repository. The Repository is not the one that instantiates the Context, so it shouldn't dispose of it either. The UnitOfWork that encapsulates multiple repositories is responsible for creating and disposing the Context and you will call a Save method on your UnitOfWork.
Code can look like this:
using (IUnitOfWork unitOfWork = new UnitOfWork())
{
PersonRepository personRepository = new PersonRepository(unitOfWork);
var person = personRepository.FindById(personId);
ProductRepository productRepository = new ProductRepository(unitOfWork);
var product= productRepository.FindById(productId);
p.CreateOrder(orderId, product);
personRepository.Save();
}

Unity and constructors

Is it possible to make unity try all defined constructors starting with the one with most arguments down to the least specific one (the default constructor)?
Edit
What I mean:
foreach (var constructor in concrete.GetConstructorsOrderByParameterCount())
{
if(CanFulfilDependencies(constructor))
{
UseConstructor(constructor);
break;
}
}
I don't want Unity to only try the constructor with most parameters. I want it to continue trying until it finds a suitable constructor. If Unity doesn't provide this behavior by default, is it possible to create an extension or something to be able to do this?
Edit 2
I got a class with two constructors:
public class MyConcrete : ISomeInterface
{
public MyConcrete (IDepend1 dep, IDepend2 dep2)
{}
public MyConcrete(IDepend1 dep)
{}
}
The class exists in a library which is used by multiple projects. In this project I want to use second constructor. But Unity stops since it can't fulfill the dependencies by the first constructor. And I do not want to change the class since the first constructor is used by DI in other projects.
Hence the need for Unity to try resolving all constructors.
Unity will choose the constructor with the most parameters unless you explicitly tag a constructor with the [InjectionConstructor] attribute which would then define the constructor for Unity to use.
When you state a suitable constructor; that is somewhat contingent on the environment. If for instance you always want to guarantee that a certain constructor is used when making use of Unity use the attribute mentioned previously, otherwise explicitly call the constructor you want to use.
What would be the point of Unity "trying" all constructors? It's purpose is to provide an instance of a type in a decoupled manner. Why would it iterate through the constructors if any constructor will create an instance of the type?
EDIT:
You could allow the constructor with the most params to be used within the project that does not have a reference to that type within its container by making use of a child container. This will not force the use of the constructor with a single param but it will allow the constructor with 2 params to work across the projects now.
You could also switch to using the single constructor across the board and force the other interface in via another form of DI (Property Injection), not Constructor Injection...therefore the base is applicable across the projects which would make more sense.

Resources