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<TPayload> PublishRequest<TMessage, TPayload>(TMessage message, Type[] potentialResponseTypes)
where TMessage : class
{
IGenericResponse<TPayload> commandResult = null;
_bus.PublishRequest(message, c =>
{
foreach (Type responseType in potentialResponseTypes)
{
Type genericHandler = typeof(GenericHandler<,>).MakeGenericType(new[]{ responseType, typeof(TMessage)});
var handler = new Action<object>(result =>
{
commandResult = (IGenericResponse<TPayload>) result;
});
Activator.CreateInstance(genericHandler, new object[] {c, handler});
}
c.SetTimeout(10.Seconds());
});
return commandResult;
}
Generic Handler to wire it up
internal class GenericHandler<TPayload, TMessage>
where TMessage : class
where TPayload : class
{
public GenericHandler(InlineRequestConfigurator<TMessage> configurator, Action<object> handler)
{
configurator.Handle<GenericResponse<TPayload>>(handler);
}
}
Thoughts?
-
\$\begingroup\$ What type is the c variable you get when you publish a request? Is this your response? If so there's a much simpler solution that needs way less reflection. \$\endgroup\$Nick Udell– Nick Udell2014年10月02日 20:38:40 +00:00Commented Oct 2, 2014 at 20:38
1 Answer 1
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<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);
}