Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic types with MediatR #69

Closed
dannyc02 opened this issue Feb 17, 2016 · 8 comments
Closed

Generic types with MediatR #69

dannyc02 opened this issue Feb 17, 2016 · 8 comments

Comments

@dannyc02
Copy link

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.)

@jbogard
Copy link
Owner

jbogard commented Feb 17, 2016

That's possible today in MediatR, provides your handler factory knows how
to create it. StructureMap for example can do that.

On Wednesday, February 17, 2016, Dan C notifications@github.com wrote:

Hi @jbogard https://github.com/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(item))

public class CreateItemCommand : IRequest where T:
ISomeInterface

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


Reply to this email directly or view it on GitHub
#69.

@dannyc02
Copy link
Author

Thanks for the speedy response @jbogard!

I've got this working by explicitly registering the in StructureMap, like so:

For<IRequestHandler<CreateItemCommand<Ping>, Ping>>().Use<CreateItemCommandHandler<Ping>>();

Is there a way to register this in StructureMap to handle all object types passed in? Something along these lines:

For<IRequestHandler<CreateItemCommand<T>, T>>().Use<CreateItemCommandHandler<T>>();

@khellang
Copy link
Contributor

@dannyc02
Copy link
Author

@khellang I'd attempted to use that method from that article without much luck :(
The article only has one 'level' deep of generics, like this:

public interface IHandler<TEvent>

where what I'm trying to achieve is this:

public interface IHandler<TEvent<TObjectType>>

Here's a snippet of what I've got in a single test - any help would be greatly appreciated.

[Test]
        public void ShouldResolveGenericHandler()
        {
            var container = new Container(cfg =>
            {
                cfg.Scan(scanner =>
                {
                    scanner.TheCallingAssembly();
                    scanner.IncludeNamespaceContainingType<Ping>();
                    scanner.WithDefaultConventions();
                    scanner.AddAllTypesOf(typeof(IRequestHandler<,>));
                    scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>));
                });
                cfg.For<SingleInstanceFactory>().Use<SingleInstanceFactory>(ctx => t => ctx.GetInstance(t));
                cfg.For<MultiInstanceFactory>().Use<MultiInstanceFactory>(ctx => t => ctx.GetAllInstances(t));
                cfg.For<IMediator>().Use<Mediator>();
            });

            var mediator = container.GetInstance<IMediator>();

            var response = mediator.Send(new CreateItemCommand<Ping>());

            response.Message.Should().NotBeNull();
        }


        public class CreateItemCommand<T> : IRequest<T>
        {

        }

        public class CreateItemCommandHandler<T> : IRequestHandler<CreateItemCommand<T>, T>
        {
            public T Handle(CreateItemCommand<T> message)
            {
                return default(T);
            }
        }

When looking at WhatDoIHave() - I can see the IRequestHandler in there:

IRequestHandler<CreateItemCommand<T>, T> MediatR Transient CreateItemCommandHandler<T> (Default)

However, when calling it, I get the following error:
----> StructureMap.StructureMapConfigurationException : No default Instance is registered and cannot be automatically determined for type 'IRequestHandler<CreateItemCommand<Ping>, Ping>'

Any ideas how to configure this with structuremap please @jbogard @khellang?

@jbogard
Copy link
Owner

jbogard commented Feb 18, 2016

I think you'll have to ask the StructureMap people on this one. But likely
you'll need to create a custom type scanner.

On Thursday, February 18, 2016, Dan C notifications@github.com wrote:

@khellang https://github.com/khellang I'd attempted to use that method
from that article without much luck :(
The article only has one 'level' deep of generics, like this:

public interface IHandler

where what I'm trying to achieve is this:

public interface IHandler<TEvent>

Here's a snippet of what I've got in a single test - any help would be
greatly appreciated.

[Test]
public void ShouldResolveGenericHandler()
{
var container = new Container(cfg =>
{
cfg.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.IncludeNamespaceContainingType();
scanner.WithDefaultConventions();
scanner.AddAllTypesOf(typeof(IRequestHandler<,>));
scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>));
});
cfg.For().Use(ctx => t => ctx.GetInstance(t));
cfg.For().Use(ctx => t => ctx.GetAllInstances(t));
cfg.For().Use();
});

        var mediator = container.GetInstance<IMediator>();

        var response = mediator.Send(new CreateItemCommand<Ping>());

        response.Message.Should().NotBeNull();
    }


    public class CreateItemCommand<T> : IRequest<T>
    {

    }

    public class CreateItemCommandHandler<T> : IRequestHandler<CreateItemCommand<T>, T>
    {
        public T Handle(CreateItemCommand<T> message)
        {
            return default(T);
        }
    }

When looking at WhatDoIHave() - I can see the IRequestHandler in there:

IRequestHandler<CreateItemCommand, T> MediatR Transient
CreateItemCommandHandler (Default)

However, when calling it, I get the following error:
----> StructureMap.StructureMapConfigurationException : No default
Instance is registered and cannot be automatically determined for type
'IRequestHandler<CreateItemCommand, Ping>'

Any ideas how to configure this with structuremap please @jbogard
https://github.com/jbogard @khellang https://github.com/khellang?


Reply to this email directly or view it on GitHub
#69 (comment).

@dannyc02
Copy link
Author

Ok thanks @jbogard.

Will report back findings.

@jeremydmiller
Copy link

@dannyc02 See this http://structuremap.github.io/generics/ and this http://structuremap.github.io/registration/auto-registration-and-conventions/. I'd urge you to be cautious about doing this though. You could easily get into a situation where the team just isn't going to be able to unravel the very fancy generics auto-registrations.

@dannyc02
Copy link
Author

@jeremydmiller thanks for the info, really helped.

I managed to get it working using a custom convention, gist here: https://gist.github.com/dannyc02/6d42b90154d8478dc6fd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants