HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Handling multiple MassTransit response types

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
handlingmasstransitresponsemultipletypes

Problem

I needed to publish a message across the ESB (MassTransit) that will return a different type of object depending on how the message is processed. I wanted to implement this in a generic way so I could wire up other services with similar requirements in the same way.

Publish a request

public IGenericResponse PublishRequest(TMessage message, Type[] potentialResponseTypes)
        where TMessage : class
{
    IGenericResponse commandResult = null;

    _bus.PublishRequest(message, c =>
    {
        foreach (Type responseType in potentialResponseTypes)
        {
            Type genericHandler = typeof(GenericHandler).MakeGenericType(new[]{ responseType, typeof(TMessage)});

            var handler = new Action(result =>
            {
                commandResult = (IGenericResponse) result;
            });

            Activator.CreateInstance(genericHandler, new object[] {c, handler});
        }

        c.SetTimeout(10.Seconds());
    });

    return commandResult;
}


Generic Handler to wire it up

internal class GenericHandler
    where TMessage : class
    where TPayload : class
{
    public GenericHandler(InlineRequestConfigurator configurator, Action handler)
    {
        configurator.Handle>(handler);
    }
}


Thoughts?

Solution

It's possible, providing c is your response from the bus, to do a lot of this without needing Reflection. Instead we can use a separate method and the joys of implicit typing to work out the type of TResponse for us.

Proposed solution

public IGenericResponse PublishRequest(TMessage message, Type[] potentialResponseTypes)
        where TMessage : class
{
    IGenericResponse commandResult = null;

    _bus.PublishRequest(message, response =>
    {
        foreach (Type responseType in potentialResponseTypes)
        {
            var genericHandler = CreateHandler(response, message);
        }

        c.SetTimeout(10.Seconds());
    });

    return commandResult;
}

private GenericHandler CreateHandler(TResponse response, TMessage message)
{
    var handler = new Action(result =>
    {
        commandResult = (IGenericResponse) result;
    });
    return new GenericHandler(response, handler);
}

Code Snippets

public IGenericResponse<TPayload> PublishRequest<TMessage, TPayload>(TMessage message, Type[] potentialResponseTypes)
        where TMessage : class
{
    IGenericResponse<TPayload> commandResult = null;

    _bus.PublishRequest(message, response =>
    {
        foreach (Type responseType in potentialResponseTypes)
        {
            var genericHandler = CreateHandler(response, message);
        }

        c.SetTimeout(10.Seconds());
    });

    return commandResult;
}

private GenericHandler<TResponse, TMessage> CreateHandler<TResponse,TMessage>(TResponse response, TMessage message)
{
    var handler = new Action<object>(result =>
    {
        commandResult = (IGenericResponse<TPayload>) result;
    });
    return new GenericHandler<TResponse, TMessage>(response, handler);
}

Context

StackExchange Code Review Q#19071, answer score: 2

Revisions (0)

No revisions yet.