I'm learning MediatR and I have a problem connecting the Controller to the Handler.
Controller:
[HttpGet]
public async Task<List<PersonModel>> Get()
{
return await _mediator.Send(new GetPersonListQuery());
}
My understanding is that the Controller will invoke the Handler using _mediator.Send(). However, the argument for Send is not the Handler but the Command / Query.
In Visual Studio, I checked how many reference there are to the Handler and it says Zero. So how does the MediatR know which particular handler to call?
Thanks.
MediatR makes heavy use of generic types in order for its mechanism to work. As you probably noticed from using it, you are required to use certain interfaces in the right way in order for your requests and handlers to be usable for MediatR.
Let’s take your example to explain how this all works:
await _mediator.Send(new GetPersonListQuery());
In order for GetPersonListQuery to be accepted, it will need to implement the marker interface IRequest<TResponse> (where TResponse stands for any response type). This also works if your request class implements this interface implicitly, e.g. by implementing IRequest instead (which is a shortcut for IRequest<Unit>).
So GetPersonListQuery implements the request interface which makes it a valid request type for MediatR. In order for a handler to be able to respond to it, that handler will now need to implement IRequestHandler<GetPersonListQuery> (again, implicitly is also ok).
So you now have this constellation:
public class GetPersonListQuery : IRequest { }
public class PersonListHandler : IRequestHandler<GetPersonListQuery> { }
From the point of view of using MediatR, this is usually all that you will need to do. MediatR will connect these two, so the handler runs when your request is sent.
It does that by relying on dependency injection, most commonly the Microsoft.Extensions.DependencyInjection container. The dependency injection container basically works by collecting a list of service registrations that contain both a service type and an implementation type. When the container then needs to resolve an instance of the service type, it will look up the service registration for that and construct an object by instantiating the implementation type.
In our example, the PersonListHandler is the implementation type, and the IRequestHandler<GetPersonListQuery> interface is the service type. So when something requests an IRequestHandler<GetPersonListQuery> from the DI container, the DI container will respond to it with an instance of PersonListHandler.
So MediatR doesn’t actually do that much; in fact, the most of its complexity comes from abstracting the dependency injection container so that it can work with others as well. But if you wanted to implement this with a specific DI container in mind, the implementation could look like this (simplified pseudo-code):
public Task<object> Send(IRequest request)
{
var requestType = request.GetType(); // GetPersonListQuery
var handlerType = CreateHandlerType(requestType); // IRequestHandler<GetPersonListQuery>
var handler = GetService(handlerType); // PersonListHandler object
return await handler.Run(request);
}
So the magic mostly boils down to the magic from the DI container, with MediatR making use of the container’s ability to resolve services.
But how does the DI container know which handlers to register? That is pretty easy to explain: When you do services.AddMediatR(…) then you are essentially telling MediatR to actively scan the assembly for all types that implement IRequestHandler<T> and register those with the dependency injection container. So just by adding a new request handler to your project, AddMediatR will pick that up when the application launches, making it available to the DI container and by that to the MediatR mediator implementation.
Since MediatR relies on the DI container for resolving the request handlers, this also gives you a direct answer to the other question you had: What happens when you have multiple request handlers for one request type?
The DI container by default will only ever give you one instance when resolving a service. This means that when you have multiple handlers implementing IRequestHandler<GetPersonListQuery>, you will only get one of them. Usually, the DI container will use the latest service registration to resolve a service. So if you register two implementation types for the same service type, the later registration will overwrite the former.
As you don’t register the services yourself with AddMediatR, you cannot actively control the registration order. Since it’s iterating over all types, I would expect the registration order to be alphabetically, but I wouldn’t rely on that. If you want a specific handler to run, you should just avoid having a different handler in the same assembly.
Note that there are cases where multiple service registrations do work: The whole notification concept in MediatR (INotification and INotificationHandler) is made for the ability for multiple handlers to exist. This is using a different feature with the dependency injection container which allows you to resolve instances for all service registrations. So if you have two handlers for the same notification, both handlers will be returned by the DI container and MediatR can call them both. The rest of the handling in MediatR is really the same as with requests though.
when you create Query/Command, you use IRequest interface. then in handler you call IRequestHandler<Query/Command>. here they make relation.
At runtime, MediatR scans your project for classes implementing IRequestHandler<T> and makes note of each of them (including your IRequestHandler<GetPersonListQuery>). When you use _mediator.Send, it matches the type of the parameter to a matching IRequestHandler it found during app startup.
Related
I have a Service Fabric application with one service which is exposed to Internet (GatewayService) through an ASP.NET Web API and a couple of internal services not exposed to the Internet (let's call one of them InternalService). So far, InternalService is also an ASP.NET Web APIs, so InternalService.cs has a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] {
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.ConfigureServices((context, services) => { services.AddSingleton(serviceContext); })
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build()))
};
}
The Startup class (in Startup.cs) for InternalService configures some services, such as adding a SQL DbContext to the Dependency Injection system, and of course setting up ASP.NET with AddMvc() etc. I have a couple of ApiControllers which expose the API.
This works, BUT I don't get any real type safety with this, and it generally makes development a bit cumbersome, needing to deserialize the result manually in my GatewayService before manipulating it. So I decided to go with SF's Service Remoting instead, resulting in a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
Then I copied all the logic from the controllers into InternalService.cs too, but this lead to an issue: I don't have access to my DbContext anymore, because it was injected into the constructor of the ApiController, instantiated by ASP.NET according to the rules set in the Startup class, which isn't used anymore.
Is there a way for me to use Startup in the same way when using Service Remoting?
Can I separate the API into multiple classes, in the same way as ApiControllers are separated into multiple classes? I feel like having all exposed methods in the same class will be quite a hazzle.
I know this has already an accepted answer, but I want to add my two cents.
As you have realized, remoting has two major differences compared to WebApi:
Given a remoting interface, you have a single implementation class
The remoting implementation class is a singleton, so, even if you use DI as explained in the accepted answer, you still can't inject a DbContext per request.
I can give you some solutions to these problems:
This one is simple: create more interfaces. You can add as many remoting interfaces as you want in a single service fabric service. So, you should split your remoting API into smaller interfaces with groups that make sense (interface segregation). But, I don't think you should have many, because that would probably mean that your microservice has too many responsibilities.
A naive approach to having dependencies per request is to inject factories into the remoting class, so you can resolve and dispose dependencies in every method instead of by constructor injection. But I found a much better approach using Mediatr, which might not seem trivial, but once set up it's very easy to use. The way it works is you create a little helper class that gets an ILifetimeScope (as you use Autofac) in the constructor and it exposes an Execute method. This method will create a child LifetimeScope, resolve Mediatr and send a WrapperRequest<TRequest> (the wrapper is a trick so that the remoting input and output objects don't have to depend on Mediatr). This will allow you to implement a Handler class for each remoting operation, which will be resolved per request so that you can inject the dependencies in the constructor as you do with a WebApi controller.
It might sound confusing if you are not familiar with Mediatr and Autofac. If I have time I'll write a blog post about it.
You can use Autofac, there's an entire page that explains how to set it up:
Add the Autofac.ServiceFabric nuget package
Configure DI:
// Start with the trusty old container builder.
var builder = new ContainerBuilder();
// Register any regular dependencies.
builder.RegisterModule(new LoggerModule(ServiceEventSource.Current.Message));
// Register the Autofac magic for Service Fabric support.
builder.RegisterServiceFabricSupport();
// Register a stateless service...
builder.RegisterStatelessService<DemoStatelessService>("DemoStatelessServiceType");
// ...and/or register a stateful service.
// builder.RegisterStatefulService<DemoStatefulService>("DemoStatefulServiceType");
using (builder.Build())
{
ServiceEventSource.Current.ServiceTypeRegistered(
Process.GetCurrentProcess().Id,
typeof(DemoStatelessService).Name);
// Prevents this host process from terminating so services keep running.
Thread.Sleep(Timeout.Infinite);
}
check out the demo project.
I'm a part of team creating a "sort of" message based framework where people can register their message handlers with the dependencies they have for their handlers.
The worker, will receive messages and invoke relevant handlers. Since the handlers have dependencies so we are passing IDependecyResolver implementation through the worker constructor. Worker uses this abstraction to create these handlers.
The users of our framework can use any DI container they like so all they have to do is to implement certain interfaces that provide abstraction to their favorite DI container. My job is to provide an implementation for SimpleInjector so for our framework, SimpleInjector is supported out of box.
The problem I'm facing is that even though I register an SimpleInjectorDependencyResolver in the container, the container is not able to resolve IDependencyResolver implementation at runtime and I get this.
This is the exception I get.
ActivationException: The constructor of type ReactiveWorker<HelloModuleBase> contains the parameter with name 'map' and type IMessageHandlerMap<HelloModuleBase> that is not registered. Please ensure IMessageHandlerMap<HelloModuleBase> is registered, or change the constructor of ReactiveWorker<HelloModuleBase>.
Here is my code for registration:
registrant.Register<IDependencyResolver>(LifeSpan.Scoped);
registrant.Register<IMessageHandlerMap<TChildModule>>(t0, LifeSpan.Scoped);
the worker needs both, a message-handler map and a dependency resolver.
This is my class with parameterized constructors:
public sealed class ReactiveWorker<TOwnerModule>: IWorker
{
readonly IMessageHandlerMap<TOwnerModule> _map;
readonly IDependencyResolver _resolver;
public ReactiveWorker(IMessageHandlerMap<TOwnerModule> map, IDependencyResolver resolver)
{
_map = map;
_resolver = resolver;
}
}
I hope everyone is able to understand the scenario.
I am trying to create an abstract class/layer for all dependency resolvers which are/will be used in my project.
This sure sounds like you are applying the Service Locator anti-pattern. You might want to double check if what you're doing is Dependency Injection or Service Location and prevent Service Location whenever possible.
Furthermore, from the posted registrations, it looks like if you are trying to implement batch-registration behavior. Simple Injector does contain this functionality out of the box, and it is worth investing into Simple Injector's API to see whether you can let the tooling do the job.
Your Helper.FindConcreteImplementationsOf, for instance, looks a lot like Simple Injector's Container.GetTypesToRegister method. It returns concrete implementations of a given type, for instance:
Type[] types = container.GetTypesToRegister(typeof(IMessageHandler<>), asm);
Simple Injector also allows for mapping open-generic abstractions to open-generic implementations. Using your MessageHandlerMap<T>, for instance, you can do the following:
container.Register(
typeof(IMessageHandlerMap<>),
typeof(MessageHandlerMap<>),
Lifestyle.Scoped);
This ensures that a closed version of MessageHandlerMap<T> is created, every time a closed version of IMessageHandlerMap<T> is requested. This does, however, rely on Simple Injector's Auto-Wiring ability, which means that Simple Injector must be able to inject all dependencies into the class's constructor. This might mean you have to change the constructor of MessageHandlerMap<T> in order to let Simple Injector Auto-Wire the type.
Because its unclear to me what the function of MessageHandlerMap<T> is and how its implementation looks like, I'm unable to fully grasp what you're trying to achieve, and can't, therefore, not give you more specific advise about making changes to your design.
Good luck.
Reading the Simple injector docs to get a handle on how it all works and I read the below paragraph. I understand what its explaining apart from the part in bold. What does it mean?
The technique for keeping this dependency to a minimum can be achieved by designing the types in your application around the constructor injection pattern: Define all dependencies of a class in the single public constructor of that type; do this for all service types that need to be resolved and resolve only the top most types in the application directly (i.e. let the container build up the complete graph of dependent objects for you)
Ignoring my lack of understanding regarding the sentence above I ploughed on but when trying to set up Simple injector for Web api came across this line of code container.RegisterWebApiControllers(GlobalConfiguration.Configuration); With this explanation
Because controllers are concrete classes, the container will be able to create them without any registration.
Does this mean if I have a bunch of classes that don't rely on an interface, I can create them using a single line of code? (if so how, should I).
What this means is a good practice of not relying on the DI-container in your code apart from some top-level where you have to do that to "kick-start" the application.
That will mean that all your classes will just have constructor dependencies in the form of interfaces and will not do Container.Resolve. This will only be called on the top level of you application.
In some frameworks you won't even have to do that yourself because it's a part of how framework operates. As far as I remember in .Net core e.g. you won't need to do a resolve, but it will happen inside framework when the controllers will be initiated.
Because controllers are concrete classes, the container will be able
to create them without any registration.
This means you won't have to register the controllers themselves in the container. Container will only resolve controller dependencies themselves, create controllers and pass all of the resolved dependencies in them.
P.S. Resolving only in the root of you application is nothing specific for the SimpleInjector. It is a good practice that can be applied to any container and SimpleInjector can be used even if you don't follow it, which probably no one these days would recommend.
do this for all service types that need to be resolved and resolve only the top most types in the application directly
What this means is that, once you solely use Constructor Injection as a way for a class to get a hold of its dependencies, you will end up building object graphs that are potentially many layers deep. Take this object graph for instance:
new HomeController(
new ProductService(
new SqlProductRepository(
new CommerceContext(connectionString)),
new AspNetUserContextAdapter(
httpContextAccessor)));
PRO TIP: Did you know that you can let Simple Injector visualize your object graphs for you inside the debugger? This is explained here.
Here you see that HomeController has one dependency (IProductService) that it gets through its constructor. ProductService itself has two dependencies (IProductRepository and IUserContext) that are as well supplied through its constructor. This can go many layers deep.
Having Constructor Injection as the sole means to supply dependencies to a class means that the class is not allows to request them itself by calling back into the Container. This is a well-established anti-pattern called Service Locator. Constructor Injection simplifies your classes and allows the Container to analyze the object graph for you and detect any anomalies.
and resolve only the top most types in the application directly
When the whole object graph is constructed using Constructor Injection, it means that you only have to ask for a HomeController, which is the top most type in the graph. Nothing depends on HomeController; HomeController depends on everything (implicitly). All application behavior is invoked through these top most types. In an MVC application these typically are controllers, HTTP handlers and modules.
Because controllers are concrete classes, the container will be able to create them without any registration.
This statement is a bit misleading. Yes, it is true that Simple Injector will be able to create a requested concrete type for you, even if that type isn't registered. As explained here in the documentation however, it is best to always register your root types in the container. This ensures that the container knows about those types and it allows analysis and verification on those types as well. Not registering those concrete root types will give you a false sense of security when you call container.Verify(). Verify is only able to verify on the registrations that it knows of. When an unregistered concrete type is referenced as a dependency, the container still knows about it, but that obviously doesn't hold for root types, since nothing depends on them.
WARNING: In Simple Injector v5, this behavior is likely going to change. By default, Simple Injector v5 will probably not allow concrete unregistered root types to be resolved. see
I am using simple injector for my web api project. I have a service which requires a session token in order for it to instantiate.
public class CustomerService
{
public CustomerService(Auth auth, IRepositoryFactory repositoryFactory)
{
// make post call to another web api for validation
SomeWebApiCallToValidateAuth.vaildate(auth);
}
}
So for this service, it requires an auth token and a repositoryFactory. I want it to be able to inject the auth parameter (which comes from the http web request) and at the same time to resolve the repository factory with the specified implemented thats registered to the container.
But I am not sure how to register this with simple injector or if there is a way around it. Any help would be great. Thanks.
Your current approach has several downsides:
You inject runtime data into the constructor of your component, which can lead to complications.
You make use of an Abstract Factory, which is often not the best abstraction.
Your constructor invokes validation, while it should do nothing other than storing its incoming dependencies. This way you can compose your object graphs with confidence.
Concerning the factory: Inject an IRepository rather than an IRepositoryFactory. This might require you to hide the real repository behind a proxy, as explained here.
Concerning the Auth value, it depends on the need, but if the Auth value is an important part of the API of CustomerService, this justifies adding Auth as argument on the methods of CustomerService. If it is an implementation detail, inject an IAuthProvider abstraction of some sort that allows you to retrieve the value at runtime (after the object graph is built). Again, this all is described in this article.
I'm trying to instantiate a SecondViewModel from a MainViewModel injecting in this second one paramaters that are services registered in the IoCContainer and objects from the MainVM.
The code is something of this kind:
class MainViewModel
{
public MainViewModel()
{
}
private string message = "the message";
public string Message { get; set; }
}
class SecondViewModel
{
public SecondViewModel(IService service, string message)
{
}
}
now, i know i can make the IoC Container inject a SecondViewModelFactory (that carries the service instance) into the MainViewModel, so it can create the SVM through it, but what if the implementation of IService is very heavy and i don't want to instantiate it but when i really need it.
And what if i have to instantiate other ViewModels in a similar way? Do I have to create tons of VMFactories and constructor's parameters?
And in case I use a generic ViewModelFactory, it would need to be instantiated passing all the services needed by every ViewModel I have, regardless if they will be created or not.
Do you know any better solution to my case?
In general, the creation of services should not be heavy. Their constructor should do nothing more than storing the incoming dependencies. If it uses some heavy resources in the background, they shouldn't be accessed through the constructor. This keeps the constructor simple (prevents you from having to test it) and allows the object graph to be composed very rapidly.
If there is really no way around this, there are basically two patterns you can apply:
1. Factories
You can inject a factory to delay the creation of a type. Factories are also useful when objects are created that should be controlled explicitly (for instance, instances that should be disposed as soon as possible). There are several ways of creating factories. Some people like to inject Func<T> or Lazy<T> dependencies into their services, but I find this too implicit. I rather inject an ISomeServiceFactory, since I find this more readable. Downside is that you need to define a new interface for this. However, if you find yourself having many factory interfaces, you probably have a problem in your design anyway.
2. Proxies
Instead of creating a factory, you can hide the service behind a proxy. This proxy can implement the same interface as the service and will do the delayed execution for you. This prevents you from letting the application take a dependency on a different interface (an IServiceFactory or Lazy<T> for instance). Especially Lazy<T> leaks details about the creation into the consumer of such a dependency. You can still inject a Lazy<T> into this proxy, if that's convenient. That's not a problem. That proxy would typically be part of your composition root and the rest of your application would still be dependend on your IService and not your Lazy<IService>.
Please be aware that the use of factories, proxies and lazy initiation does complicate the wiring of the container. So don't use if unless you measured that you really need it. They complicate things, because of the indirection, which makes it harder to follow interlectually. And they make it harder to verify your configuration using automated tests. For more information about verifying your container, take a look here and here.
Most IoC Containers supports Lazy dependency to with Lazy<> to avoid creating expensive class immediately.
So in your code, you can make lazy for your expensive IService:
class SecondViewModel
{
public SecondViewModel(Lazy<IService> service, string message)
{
}
}
You can use some popular IoC Containers and see how they support lazy loading: Autofac or NInject