Code Monkey home page Code Monkey logo

mediatr's Introduction

MediatR

CI NuGet NuGet MyGet (dev)

Simple mediator implementation in .NET

In-process messaging with no dependencies.

Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance.

Examples in the wiki.

Installing MediatR

You should install MediatR with NuGet:

Install-Package MediatR

Or via the .NET Core command line interface:

dotnet add package MediatR

Either commands, from Package Manager Console or .NET Core CLI, will download and install MediatR and all required dependencies.

Using Contracts-Only Package

To reference only the contracts for MediatR, which includes:

  • IRequest (including generic variants)
  • INotification
  • IStreamRequest

Add a package reference to MediatR.Contracts

This package is useful in scenarios where your MediatR contracts are in a separate assembly/project from handlers. Example scenarios include:

  • API contracts
  • GRPC contracts
  • Blazor

Registering with IServiceCollection

MediatR supports Microsoft.Extensions.DependencyInjection.Abstractions directly. To register various MediatR services and handlers:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Startup>());

or with an assembly:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly));

This registers:

  • IMediator as transient
  • ISender as transient
  • IPublisher as transient
  • IRequestHandler<,> concrete implementations as transient
  • IRequestHandler<> concrete implementations as transient
  • INotificationHandler<> concrete implementations as transient
  • IStreamRequestHandler<> concrete implementations as transient
  • IRequestExceptionHandler<,,> concrete implementations as transient
  • IRequestExceptionAction<,>) concrete implementations as transient

This also registers open generic implementations for:

  • INotificationHandler<>
  • IRequestExceptionHandler<,,>
  • IRequestExceptionAction<,>

To register behaviors, stream behaviors, pre/post processors:

services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly);
    cfg.AddBehavior<PingPongBehavior>();
    cfg.AddStreamBehavior<PingPongStreamBehavior>();
    cfg.AddRequestPreProcessor<PingPreProcessor>();
    cfg.AddRequestPostProcessor<PingPongPostProcessor>();
    cfg.AddOpenBehavior(typeof(GenericBehavior<,>));
    });

With additional methods for open generics and overloads for explicit service types.

mediatr's People

Contributors

alexandruchirita4192 avatar asimmon avatar bartosz6 avatar chrismissal avatar dadhi avatar daniel-white avatar dariogriffo avatar driekus77 avatar fredimachado avatar geirsagberg avatar henkmollema avatar jbogard avatar jchannon avatar jordy-asebp avatar jordywells avatar kahbazi avatar khellang avatar lilasquared avatar lodewijksioen avatar maniglia avatar mderriey avatar remcoros avatar seesharper avatar sergergood avatar shumigaj avatar simoncropp avatar sq735 avatar twadrianlis avatar vegar avatar z4kn4fein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mediatr's Issues

Not Installing on .NET 4.0

The wiki says:

Cross-platform, distributed as a portable class library, supporting .NET 4+, Silverlight 5, Windows 8, Windows Phone 8, Xamarin.Android, Xamarin.iOS, Xamarin.Unified, ASP.NET 5 and ASP.NET Core 5.

When running "Install-Package MediatR" on a .NET 4.0 project, I get this error:

Could not install package 'MediatR 1.0.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the package does not contain any assembly references or content files that are compatible with that framework.

How to disambiguate Commands and Queries?

I get that Commands and Queries are basically just Requests, and that they both follow very similar structures.

Now, I want to decorate my CommandHandlers so that they automatically Commit after they complete. I don't want to do this for my Queries, obviously.

Using MediatR all I see are IRequest and IRequestHandler objects. I'd like to disambiguate between Commands and Queries so that I can decorate only Commands. Have you done this before? How did you tackle this?

Multiple notifications handled by the same handler instance with structuremap

I have multiple notifications and I need to have only 1 handler instance for all the notifications of type IBusEvent.

Here is my current situation

The notifications

public interface IBusEvent : IAsyncNotification
{
}

public class RecEnded : IBusEvent
{
    public long RecId { get; set; }

    public RecEnded(long recId)
    {
        RecId = recId;
    }
}

public class RecStarted : IBusEvent
{
    public long RecId { get; set; }
    public int InitiatorCellId { get; set; }

    public RecStarted(long recId, int initiatorCellId)
    {
        RecId = recId;
        InitiatorCellId = initiatorCellId;
    }
}

The handler

I have only one handler for both of these Notifications.

public class BusEventHandler : IAsyncNotificationHandler<IBusEvent>, IDisposable
{
    private IBusConfig _config;

    public BusEventHandler(IBusConfig config)
    {
        _config = config;
        // connect to the bus
    }

    public async Task Handle(IBusEvent notification)
    {
         // send package to the bus
    }

    public void Dispose()
    {
         // close & dispose connection
    }

IOC

public class MediatorRegistry : Registry
{
    public MediatorRegistry()
    {
        For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t));
        For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => ctx.GetAllInstances(t));
        For<IMediator>().Use<Mediator>();
    }
}

public class HandlersRegistry : Registry
{
    public HandlersRegistry()
    {
        // I have multiple configs for IBusConfig.
        // get the configuration from the config file
        List<IBusConfig> configs = AppSettings.GetBusConfigs();
        foreach (IBusConfig config in configs)
             For(typeof(IAsyncNotificationHandler<IBusEvent>))
                 .Singleton()
                 .Add(i => new BusEventHandler(config));
    }

}

What I need

With this IOC registry I receive 2 instances of BusEventHandler for every IBusConfig.

I need to have only 1 instance of BusEventHandler for every IBusConfig.

The only way I could accomplish the good behavior is by changing the MediatorRegistry

public class MediatorRegisty : Registry
{
    public MediatorRegisty()
    {
        For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t));
        For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => TryGetAllInstances(ctx, t));
        For<IMediator>().Use<Mediator>();
    }

    private static IEnumerable<object> TryGetAllInstances(IContext ctx, Type t)
    {
        if (t.GenericTypeArguments[0].GetInterfaces().Contains(typeof(IBusEvent)))
            return ctx.GetAllInstances(typeof(IAsyncNotificationHandler<IBusEvent>));
        else
            return ctx.GetAllInstances(t);
    }
}

Is there no better way to accomplish this without changing the MediatorRegistry?

Generic types with MediatR

Hi @jbogard ,

I was wondering if it's possible to extend this framework to handle generic types in requests? Here's an example of what I was hoping to achieve:

mediator.Send(new CreateItemCommand<ItemType>(item))

public class CreateItemCommand<TItemType> : IRequest<T> where T: ISomeInterface

(Apologies if this isn't the correct place to ask this question.)

Process events in isolation

It would be nice if you could pass in a parameter to the publish method, or a global configuration which allowed events to be processed in isolation, i.e.: if one fails should it continue processing the next ones. This is happening in a process but in between states, using aspects I might want to add a queue just to persist some messages. Also if I add in transactions my Unit of Work will be quite expensive if I have a couple of handlers per event.

Just an idea:

    public void Publish(INotification notification, ref IEnumerable<FailedNotificationHandlerWrapperExecution> failedHandlers, bool processInIsolation = false)
    {
        var notificationHandlers = GetNotificationHandlers(notification);

        if(!processInIsolation)
        {
            notificationHandlers.ToList().ForEach(x => handler.Handle);
        }
        else
        {
            var failHandlers = new List<FailedNotificationHandlerWrapperExecution>();

            foreach (var handler in notificationHandlers)
            {
                try
                {
                    handler.Handle(notification);
                }
                catch(Exception ex)
                {
                    failHandlers.Add(handler, ex);
                }
            }
        }
    }

INotificationHandler for an INotification with a GenericType Argument, is this doable?

I was attempting to create a generic INotification that could then be handled by a single INotificationHandler implementation. Something like below:

public class UpdateEntity<T> : INotification {
public T Entity {get;set;}
}

public class UpdateEntityHandler<T> : INotificationHandler<UpdateEntity<T>> where T : class
{
}

I am using Ninject as my DI container and am not sure if this is related to my ninject configuration, but for some reason if I send a mediator.Publish call of my command it cannot identify the notification handler to execute. Is what I am trying to do possible, or even correct? Perhaps I have misused the concept of Notifications for handling my commands when in reality I should be using the IRequest interface. Does this make sense? If it is the case that I should be simply using the RequestHandler implementation for managing my commands as well, how would I be able to implement this same generic concept using RequestHandlers?

Cannot resolve parameter MediatR.SingleInstanceFactory singleInstanceFactory

I thought I'd give MediatR a try but keep getting autofac errors.

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MediatR.Mediator' can be invoked with the available services and parameters:
Cannot resolve parameter 'MediatR.SingleInstanceFactory singleInstanceFactory' of constructor 'Void .ctor(MediatR.SingleInstanceFactory, MediatR.MultiInstanceFactory)'.

Autofac registration

builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsSelf().AsImplementedInterfaces();

My controller

 public class PeopleController : Controller
    {
        private readonly IMediator _mediator;

        public PeopleController(IMediator mediator)
        {
            _mediator = mediator;
        }
...

Castle Windsor sample doesn't release components

The Windsor sample at https://github.com/jbogard/MediatR/blob/master/samples/MediatR.Examples.Windsor/Program.cs might keep track of components after use, as shown from the following sample:

class Program
{
    static void Main(string[] args)
    {
        var container = new WindsorContainer();
        container.Register(Component.For<SomeDisposable>().LifestyleTransient());
        container.Register(Component.For<Factory>().UsingFactoryMethod<Factory>(k => t => k.Resolve(t)));

        var factory = container.Resolve<Factory>();
        var res = factory(typeof (SomeDisposable));
        Debug.Assert(container.Kernel.ReleasePolicy.HasTrack(res));
    }

    class SomeDisposable : IDisposable
    {
        public bool Disposed { get; private set; }

        public void Dispose()
        {
            Disposed = true;
        }
    }

    delegate object Factory(Type type);
}

Worse, if resolving a component that in itself is not IDisposable, but has a dependency on IDisposable it will also get tracked and never released. Assuming the handler will have a DbContext or an ISession, these will never be released by Windsor.

Return exception if something occurred

Hello,

I have been using my own mediator classes and I am moving to MediatR.

When you send a message how to you check if an exception occurred if you need to show on the UI if everything went fine or not?

Thank You,
Miguel

Creating a second notification handler in MediatR.Examples

Nice library.

I was taking the library for a spin and attempted to create a second notification handler in MediatR.Examples like below just pasting and renaming the existing class:

public class PingedDubHandler : INotificationHandler<Pinged>
{
    private readonly TextWriter _writer;

    public PingedDubHandler(TextWriter writer)
    {
        _writer = writer;
    }

    public void Handle(Pinged notification)
    {
        _writer.WriteLine("Got pingedDub.");
    }
}

I then attempted to rerun the MediatR.Examples.Unity example and it broke on this line
container.RegisterTypes(AllClasses.FromAssemblies(typeof (Ping).Assembly), WithMappings.FromAllInterfaces);
with this exception: An unhandled exception of type 'Microsoft.Practices.Unity.DuplicateTypeMappingException' occurred in Microsoft.Practices.Unity.RegistrationByConvention.dll

Additional information: An attempt to override an existing mapping was detected for type MediatR.INotificationHandler`1[MediatR.Examples.Pinged] with name "", currently mapped to type MediatR.Examples.PingedHandler, to type MediatR.Examples.PingedDubHandler.

So to resolve that issue I changed the registration for that line to include the type name so that multiple types with the interface can be registered.

However now when running the example the send is broken because all types now have names:
An unhandled exception of type 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll

Additional information: Activation error occurred while trying to get instance of type IRequestHandler`2, key ""

Is this the expected behavior with unity or am I trying to create a second notification handler in the incorrect way?

help to use with webapi mvc6

i am trying to use inbuilt dependency injection in mvc 6.
having trouble to register SingleInstanceFactory & MultiInstanceFactory

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddMediatorHandlers(typeof(PingAsync).GetTypeInfo().Assembly);
            services.AddSingleton(typeof(IMediator),typeof(Mediator));
            services.AddSingleton(typeof(SingleInstanceFactory), ??????
        }

Architectural help for specifying which handler to use

I'm working on a system where I've started using Mediatr to separate out our commands / queries.

One such request is GetAccountInformation

I've simplified the logic down, but the kind of issue I'm having, is we need to query a service to find out which sub-system to use, in order to get the account information.

Probably better to illustrate with code...

So, currently, in a 'core' namespace/assembly, I have

public class GetAccountInformationRequest : IAsyncRequest<AccountInformation>
{
    public string AccountReference {get; set}
}

Then, the handler looks something like this

public class GetAccountInformationRequestHandler :       
    IAsyncRequestHandler<GetAccountInformationRequest , AccountInformation>
{
    private readonly IMediator _mediator;

    public GetAccountInformationRequestHandler(IMediator mediator)
    {
        _mediator = mediator;
    }

    public async Task<AccountInformation> Handle(GetAccountInformationRequest request)
    {
        //this sends a different request off to another handler which determines which sub system to use
        var subSystem = await _mediator.SendAsync(new GetAccountSubSystemRequest(request.AccountReference));

        //this is rubbish, but I've only done this to illustrate the kind of thing I need to do
        if(subSystem == 'SystemA')
            return await _mediator.SendAsync(new SystemA.GetAccountInformationRequestFromSystemRequest(request.AccountReference));
        if(subSystem == 'SystemB')
            return await _mediator.SendAsync(new SystemB.GetAccountInformationRequestFromSystemRequest(request.AccountReference));
        if(subSystem == 'SystemC')
            return await _mediator.SendAsync(new SystemC.GetAccountInformationRequestFromSystemRequest(request.AccountReference));

        throw new Exception("Unknown sub system");
    }
}

As you can see, I've then got additional namespaces (in separate assemblies) with the specific requests in -
This does feel a bit rubbish. For a start, it feels like there's a lot of duplication here - really, I just need the specific handlers
And the obvious violation of Open/Closed

Any ideas?

Mediator's async methods obfuscate the source of an error

For some reason, Mediator is obfuscating the true source of an exception when an error occurs in an async handler. It's a bit hard to explain exactly what's happening, so I've created a simple repo repository with a couple of specs to show what's going on. The repo is here: https://github.com/MattHoneycutt/MediatorRepoSample

Basically, using the implementation of Mediator that's in the assembly results in a stack trace that looks like this:

System.AggregateException : One or more errors occurred.
----> System.NullReferenceException : Object reference not set to an instance of an object.
at System.Threading.Tasks.Task.Wait(Int32ย millisecondsTimeout,ย CancellationTokenย cancellationToken)
at MediatorReproCase.Specs.SomeServiceSpecs.when_calling_a_method_that_throws_an_exception_with_the_real_mediator.then_it_throws_an_exception_that_includes_the_actual_source_of_the_error() in SomeServiceSpecs.cs: line 28
--NullReferenceException
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Taskย task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Taskย task)
at MediatR.Mediator.d__0`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Taskย task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Taskย task)
at MediatorReproCase.Specs.SomeService.d__0.MoveNext() in SomeService.cs: line 17

Using the exact same implementation of Mediator, but within the local project, produces a stack trace like this:

System.AggregateException : One or more errors occurred.
----> System.NullReferenceException : Object reference not set to an instance of an object.
at System.Threading.Tasks.Task.Wait(Int32ย millisecondsTimeout,ย CancellationTokenย cancellationToken)
at System.Threading.Tasks.Task.Wait()
at MediatorReproCase.Specs.SomeServiceSpecs.when_calling_a_method_that_throws_an_exception_with_the_local_copy_of_mediator.then_it_throws_an_exception_that_includes_the_actual_source_of_the_error() in SomeServiceSpecs.cs: line 50
--NullReferenceException
at MediatorReproCase.Specs.GetBooleanHandler.d__0.MoveNext() in GetBooleanHandler.cs: line 14
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Taskย task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Taskย task)
at MediatorReproCase.Specs.MyMediator.d__0`1.MoveNext() in MyMediator.cs: line 31
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Taskย task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Taskย task)
at MediatorReproCase.Specs.SomeService.d__0.MoveNext() in SomeService.cs: line 17

Notice that the later includes the actual source of the exception, while the former does not.

My best-guess is that something is being inlined or altered when Mediator is compiled for release, but I can't seem to reproduce that behavior. Any ideas?

How do you control the order of multiple Pre/PostRequestHandlers?

I manage to modify the framework using a custom DependencyResolver and SimpleInjector and get both Pre/Post/MediatorPipeline and the handler decorator example work. I felt the Pre/Post approach give me much better control when I need to access and modify common base request/response.

But how do I control the order of multiple Pre/Post? The default IoC registration seems giving little control over the order. Thanks

How to Mock - Moq

I have a Request Handler that gets a IMediator injected via constructor injection (Autofac). The request handler under test conditionally calls other Send messages internally. I am trying to Mock the mediator injected using Moq and ensure that the send calls happen as expected. I am unable to find examples of how to do this. Can you provide and assistance or references as how to Mock the mediator to verify that the send call is made?

Thanks,
Brian

MVC client consuming Web API with MediatR implementation

How would one consume an ASP Web API service that makes use of Request(Query) and Response(Result) - Web API that implements MediatR - that can be strongly typed to class instances? To Simplify, if I have a Request Model in my web API that "passes" data to my handler, would a view model in a project such as a standard ASP MVC project need to follow the same structure; for example: if the Request model (or a Query in this case) is being passed to the handler and has a property of an ID of type integer, would the front end client application that has a view model need to follow the same structure of the request being pushed through; in that the view model in mention should also have a property of an ID that is of type integer, and in doing so won't this result in replication of code? (the view model trying to match up with the query/request). With Reference to article: https://lostechies.com/jimmybogard/2015/05/05/cqrs-with-mediatr-and-automapper/

Using Ninject, MVC , Web API

I'm having quite the headache trying to set MediatR with MVC 5.
I've created a new mvc project, setup Ninject, verified that it worked with a dummy interface.
Next I copy the example code of the ninject sample, all compiled but on launching my MVC controller can't resolve IMediater.

//In my NinjectWebCommon.cs
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Components.Add<IBindingResolver, ContravariantBindingResolver>();
            kernel.Bind(scan => scan.FromAssemblyContaining<IMediator>().SelectAllClasses().BindDefaultInterface());
            kernel.Bind(scan => scan.FromAssemblyContaining<Person>().Select(x => x.Namespace.Contains("MvcApp.PersonApi")).BindAllInterfaces());
            kernel.Bind<SingleInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.Get(t));
            kernel.Bind<MultiInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.GetAll(t));
            kernel.Bind<IPonny>().To<Ponny>();
        }

And I get

Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
 4) Injection of dependency IntPtr into parameter method of constructor of type ServiceLocatorProvider
 3) Injection of dependency ServiceLocatorProvider into parameter serviceLocatorProvider of constructor of type Mediator
 2) Injection of dependency IMediator into parameter meddy of constructor of type HomeController
 1) Request for HomeController

Suggestions:
 1) Ensure that you have defined a binding for IntPtr.
 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
 3) Ensure you have not accidentally created more than one kernel.
 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
 5) If you are using automatic module loading, ensure the search path and filters are correct.

Any ideas?

Can't update to beta-004

Hi, i wanted to upgrade to beta-004 but reciving a strange error message from nuget.
Upgrade to beta-002 is working fine, so I found a difference between the two versions.
In beta-004
image
In beta-002
image

Is this correct, the "Unsupported, Version=0.0" ?

I don't know if it's helpfull but here is the nuget error
image

System.InvalidOperationException: Failed to add reference to 'System.Runtime'. Please make sure that it is in the Global Assembly Cache. ---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.
at VSLangProj.References.Add(String bstrPath)
at NuGet.PackageManagement.VisualStudio.VSMSBuildNuGetProjectSystem.AddGacReference(String name)
at NuGet.PackageManagement.VisualStudio.VSMSBuildNuGetProjectSystem.AddFrameworkReference(String name)
--- End of inner exception stack trace ---
at NuGet.PackageManagement.NuGetPackageManager.d__d2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NuGet.PackageManagement.UI.UIActionEngine.d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NuGet.PackageManagement.UI.UIActionEngine.d__0.MoveNext()

Small change: Really async for PublishAsync

In the code for PublishAsync(IAsyncNotification notification) it is
public async Task PublishAsync(IAsyncNotification notification)
{
var notificationHandlers = GetNotificationHandlers(notification);

        foreach (var handler in notificationHandlers)
        {
            await handler.Handle(notification));
        }
    }

This manner the PublishAsync waits for each handler to execute.
( put
await Task.Delay(2000);
in PingedAsyncHandler
and
await Task.Delay(5000);
in PingedAlsoAsyncHandler
and you will see that total await time is 2000 + 5000)

It will be real async if executed in parallel.
The code will be:

public async Task PublishAsync(IAsyncNotification notification)
{
var notificationHandlers = GetNotificationHandlers(notification);
var tasks =new List();
foreach (var handler in notificationHandlers)
{
tasks.Add( handler.Handle(notification));
}
await Task.WhenAll(tasks);
}

What do you think ?

Mediatr and Web API

Are there any known issues using Mediatr and StructureMap with Web API? We tried to run the example from the Mediatr source on two different machines and are getting an exception

Make Publish Non generic

Is there a reason why Publish needs to be Publish<TNotificaiton>(TNotification notification) and can't be Publish(INotification notification)?

Using the latter you can still build

var serviceType = typeof(INotificaitonHandler<>).MakeGenericType(notification.GetType());

and resolve it using the MultiInstanceFactory. Makes it easier for clients to consume the IMediator when they need to Publish a notification that is passed to them as an object by simply casting it to INotification.

Signed Nuget Version

I'd love to use MediatR in my production environment, but the Nuget package does not provide a signed version for .Net 4.5. Any reason for this?

Are Decorators Supported?

are there any issues with using decorators for the request handlers for example using simple injector?

Create marker interface for handler

Hi Jimmy,

It would be nice if you could add a marker interface (IRequestHandler) and make all handler interfaces extend this interface, this would allow me to register all handlers in one go like so:

Without marker interface

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .AsClosedTypesOf(typeof(IRequestHandler<,>))
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .AsImplementedInterfaces();

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .AsClosedTypesOf(typeof(IAsyncRequestHandler<,>))
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .AsImplementedInterfaces();

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .AsClosedTypesOf(typeof(INotificationHandler<>))
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .AsImplementedInterfaces();

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .AsClosedTypesOf(typeof(IAsyncNotificationHandler<>))
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .AsImplementedInterfaces();

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .Where(t => t.IsClass && typeof(IRepository).IsAssignableFrom(t))
                    .AsImplementedInterfaces()
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .InstancePerRequest();

With marker interface

                builder.RegisterAssemblyTypes(AssemblyUtils.GetAssemblies)
                    .AsClosedTypesOf(typeof(IRequestHandler))
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .AsImplementedInterfaces();

Mediator pipeline with notifications

Hi @jbogard

This isn't really an issue, it's more like a question.

I'd like to have my MediatorPipeline to publish notifications. I think the're a couple of different ways to achieve that and I thought of:

  1. Publish notifications from my post request handlers.The advantage is I leave my Pipeline pretty lean with only request type of objects (pre, actual and post) and also validators. Example here: https://gist.github.com/afgallo/5fc2464ff4f15dd19bd3
  2. Extend the pipeline to decorate with an object of type NotificationHandler. However, I'd have to change their contract so it obeys the generic variance and am not that familiar with it to be honest.

How would you do this? Is my example OK or have I completely missed the point here?

By the way, this is a fantastic library. It solves so many day-to-day problems that any consulting firms would charge you $$$$$ for it !

Thanks
Andre

CoreCLR

Is this supposed to work on coreclr? I've tried to get it to build but no joy ๐Ÿ˜ข

Unity won't ResolveAll for 'unnamed' type registrations.

Hi!

Thanks for writing this library! I notice a problem with the Unity configuration. Unity's ResolveAll method will only produce instances which have an explicit named. Therefore, none of the notification handler classes will be created during the Publish/PublishAsync calls.

To fix this, I simply modify the RegisterTypes call in MediatR.Examples.Unity.Program.BuildMediator method and provide both a name and lifetime function...

        container.RegisterTypes(AllClasses.FromAssemblies(typeof (Ping).Assembly), WithMappings.FromAllInterfaces, GetName, GetLifetimeManager);

The helper functions...

    static bool IsNotificationHandler(Type type)
    {
        return type.GetInterfaces().Any(x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof(INotificationHandler<>) || x.GetGenericTypeDefinition() == typeof(IAsyncNotificationHandler<>)));
    }

    static LifetimeManager GetLifetimeManager(Type type)
    {
        return IsNotificationHandler(type) ? new ContainerControlledLifetimeManager() : null;
    }

    static string GetName(Type type)
    {
        return IsNotificationHandler(type) ? string.Format("HandlerFor" + type.Name) : string.Empty;
    }

Now the handlers will be instantiated (once per container in this example).

John

Nuget package out of date?

It looks like nuget repository has an older version. Building samples from wiki fails to find SingleInstanceFactory and a few other classes.

WebApi, Ninject and MediatR binding issues

Hi,

I seem to have an issue while hooking up WebApi with Ninject and Mediatr. I used the example in /samples for Ninject but I keep getting this:
Error: An error occurred when trying to create a controller of type 'PeopleController'. Make sure that the controller has a parameterless public constructor.

InnerException:
Error activating IMediator More than one matching bindings are available. Matching bindings:

  1. binding from IMediator to Mediator
  2. binding from IMediator to Mediator Activation path:
  3. Injection of dependency IMediator into parameter mediator of constructor of type PeopleController
  4. Injection of dependency PeopleController into parameter resolutionRoot of constructor of type NinjectDependencyResolver
  5. Request for IDependencyResolver Suggestions:
  6. Ensure that you have defined a binding for IMediator only once.

Any ideas?
Thanks!

Nuget package doesnt include the SingleInstanceFactory/MultipleInstanceFactory delegates

I wanted to use this, and for some reason the SingleInstanceFactory/MultipleInstanceFactory delegates are not included in the Nuget package, I have verified that by using Object Browser, and making sure I am looking in right namespace by downloading the code directly from GitHub.

They just aint in the Nuget package. Nuget package I used was v1.0.0.0

Can this please be fixed

Create a Logo!

Because every project should have a logo.

MediatR lets developers create "an object that encapsulates how a series of objects interact". This can be one-to-one or one-to-many. Things we talked about as part of a design were:

  • Arrows into, and one or more arrows, out of something.
  • It could be thought of kind of like a phone switchboard.
  • Probably doesn't need the name in the logo
  • Should look nice as a square (for GitHub, and NuGet )
  • Should scale for both large (128x128) and small (32x32)

Anything else that would be valuable to know?

Question: good pattern to allow for variances in business logic?

I'm looking for a good pattern to apply to create a small variance in the business logic based on a value of a parameter of the command object.

The poor mans solution would be a if-then-else in code, but it breaks the S in SOLID, which I'm not too happy about.

Also I would like to avoid having to create a new command object just for the sake of separation.

Nancyfx and MediatR - Where to put the module logic

Hi
I'm using Nancyfx and MediatR
In my nancy module (a cousin of mvc controller)
There's some logic done by the Module itself
for example input-model-validation, response object manipulation, LoginAndRedirect, etc.
these are extensions of the nancy Module object

Common usage example: https://github.com/NancyFx/DinnerParty/blob/master/src/Modules/AccountModule.cs

Is it a good practice to move that logic into the Request Handler which will return a nancy Response object?

thanks allot :-)

MediatR - Not working while accessing via Webseal

I am trying to access my application via Webseal SSL. But the code is failing stating that it's not able to find the handler class or the dependency is not registered.. But when we try accessing the application without web seal its working.

In the application start up, we have a dependency registered as

container.RegisterType<IRequestHandler<Query, Result>, Handler>();

In order to filter out the root cause, I injected IRequestHandler<Query, Result> to the constructor and invoked the Handler. This is working fine with Webseal.

Hope you can provide help on this to resolve the issue.

Full Error Information
[{"code":null,"source":{},"title":"Internal Server Error","details":"Handler was not found for request of type Query.\r\nContainer or service locator not configured properly or handlers not registered with your container."}]

Simple Injector build failure with ncrunch

I get the following error when running the tests under nCrunch. To fix I copied the simple injector common service locator implementation into a local class rather than use the packaged version as the packaged version uses 1.0.0.0 instead of 1.3.0.0

Assembly 'MediatR, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' uses 'Microsoft.Practices.ServiceLocation, 
Version=1.3.0.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35' which has a higher version than referenced assembly 'Microsoft.Practices.ServiceLocation, 
Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35'

If you'd like a merge request let me know, feels like the proper fix here is to get simple injector to update their CSL package though.

Thoughts?

Thanks
Neil

Question: Why the Handler Wrappers?

Hi,

Like the titles says, this is not really an issue, but just a question. I was looking around the code (kudos by the way ๐Ÿ‘ ) and I notices the double Generic caches of ConcurrentDictionaries to hold the generic types of both the Generic Handler and a default Handler Wrapper.

While I do understand the first, because the type of the generic IRequestHandler<> is not know and you want to save up the MakeGeneric call, I did not get to find a reason for the Wrappers, since all they do is to call the inner handler. I did not find any hook on them or usages besides the inner call.

Did I over looked something?

Thanks in advance, and kudos again for this awesome library. It has already become a standard on both my personal and my team's professional projects.

Invoking SendAsync with reflection is broken

Hello
i have the following code. it has been working so far including v2.0 beta 5.
i started getting error of ambiguous match found because you have created overloaded method of SendAsync with cancelation token. could you tell me how to fix the following code

var requestInterface = requestType.GetInterface("IAsyncRequest`1");
var sendMethod = mediator.GetType().GetMethod("SendAsync");
var method = sendMethod.MakeGenericMethod(requestInterface.GetGenericArguments());
var task= (Task)method.Invoke(mediator, new[] {instance});
await task;
return task.GetType().GetProperty("Result").GetValue(task);

ASP.NET MVC Example

Is there a complete example of using MediaR with ASP.NET MVC including the decorator pattern pipeline for validation, authorisation?

Are there any performance concerns wiring up too many decorators?

I have the typical crosscutting stuff like validation, authorization, auditing, transaction and error logging as decorators. They check attributes on the requests and do their part. Since most of them are done via other frameworks, there's not much code in them. Right now, each is a separate decorator and wired up using SimpleInjector. It sounds like following SRP this way.

But is it really necessary? Are their any performance penalty having too many decorators? Since none of the steps are optional, is it better if I leave them all in one place? Decorator performance aside, I assume it would at least shave off a few nanoseconds reflecting attributes?

Appreciate your thought.

Can't install nuget package in project targeting .NET 4.5.2

When I try to install MediatR in a project that targets .NET Framework 4.5.2 it fails. I'm using VS 2015 RC.

PM> Install-Package MediatR -Pre

Attempting to gather dependencies information for package 'MediatR.2.0.0-beta-004' with respect to project targeting '.NETFramework, Version=v4.5.2'
Attempting to resolve dependencies for package 'MediatR.2.0.0-beta-004' with DependencyBehavior 'Lowest'
Resolving actions to install package 'MediatR.2.0.0-beta-004'
Resolved actions to install package 'MediatR.2.0.0-beta-004'
Adding package 'MediatR 2.0.0-beta-004' to folder 'C:\Users\Dev\Documents\Visual Studio 2015\Projects\App\packages'
Added package 'MediatR 2.0.0-beta-004' to folder 'C:\Users\Dev\Documents\Visual Studio 2015\Projects\App\packages'
Install failed. Rolling back...
Package 'MediatR 2.0.0-beta-004' does not exist in project 'App.Core'
Removing package 'MediatR 2.0.0-beta-004' from folder 'C:\Users\Dev\Documents\Visual Studio 2015\Projects\App\packages'
Removed package 'MediatR 2.0.0-beta-004' from folder 'C:\Users\Dev\Documents\Visual Studio 2015\Projects\App\packages'
Install-Package : Failed to add reference to 'System.Runtime'. Please make sure that it is in the Global Assembly Cache.
At line:1 char:1
+ Install-Package MediatR -Pre
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand

Move interfaces to its own assembly

It would be nice to have all the interfaces and base classes (such as Unit) moved to it's own assembly, called MediatR.Abstractions or something like that, so we could use it in class libraries without having a dependency on the concrete implementation.

For example I have a shared projet, called Domain.Shared where I share commonly used interfaces and classes (such as IEntity<T> etc.) that I'd like to share accross multiple microservices, each implementing it's own Requests and Notifications.

This is a small problem, as if I want to use a newer versions of MediatR in one of the microservices, I'd have to update all the services, when I update Domain.Shared project.

Since the interfaces rarely change, it would make sense to extract them, so our class libraries only depend on the abstractions and we only have to reference the MediatR package in the application projects (ASP.NET 5, MVC, Console Application) and not in our class libraries. Then we could use individual verisons in our microservices, like having MediatR 2.0 on OrderService and having maybe 2.0.2 on ShippingService for example

Cross-Cutting Concerns via Message Headers

I have a similar project that has some support for cross-cutting concerns (date-time stamp, current user, current user's roles) which you can check out here.

Any interest in rolling those capabilities into MediatR? I'm aware my implementation for users/roles is for old crappy Membership, but I could create an implementation for Membership and ASP.NET Identity.

As far as I know, it would require some concrete classes in order to add headers to the messages. If there's some other way to do it, let me know (assuming you're into it).

Need some help on DecorateAllWith in WebApi

I'm testing a simple ping request with a decorator.

public class ValidatorHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse>
   where TRequest : IRequest<TResponse> { ... }

In a console application, the ValidatorHandler works.

       var container = new Container(cfg =>
        {
            cfg.Scan(scanner =>
            {
                scanner.AssemblyContainingType<PingRequest>();
                scanner.AssemblyContainingType<IMediator>();
                scanner.WithDefaultConventions();
                scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>));
            });
            cfg.For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t));
            cfg.For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => ctx.GetAllInstances(t));

            var handlerType = cfg.For(typeof(IRequestHandler<,>));
            handlerType.DecorateAllWith(typeof(ValidatorHandler<,>));
        });

        var mediator = container.GetInstance<IMediator>();
        mediator.Send(new PingRequest { Message = "Ping"});

But when trying the same in a WebApi project, the ValidationHandler never wired up. I know the rest of the IoC works, because I can inject IDatabase and retrieve data. Did I miss something? Maybe need to decorate from a different place? Thanks

    public DefaultRegistry()
    {
        Scan(
            scan =>
            {
                scan.TheCallingAssembly();
                scan.AssemblyContainingType<PingHandler>();
                scan.WithDefaultConventions();
                //scan.With(new ControllerConvention());
                scan.AddAllTypesOf(typeof(IRequestHandler<,>));
            });

        var handlerType = For(typeof(IRequestHandler<,>));
        handlerType.DecorateAllWith(typeof(ValidatorHandler<,>));

        For<IMediator>().Use<Mediator>();
        For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t));
        For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => ctx.GetAllInstances(t));

        For<IDatabase>().Use(new Database("DefaultDb"));
    }

More documentation required.

I love the ideas behind this package. But I am having a lot of trouble actually wiring up decorator handlers through Castle Windsor.

Since all the power of this pattern comes from creating that pipeline of handlers, documentation in the wiki around that idea would be really useful.

http://blog.skillsmatter.com/tag/jimmy-bogard/ is a good start. And at it's high level intent is very clear. However, it does not represent an example of a complete solution, it is missing a lot of the implementation details that are required to actually get something up and running. It makes some leaps that I am just unable to follow when it comes to wiring it up all together.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.