I am using proxies and intercepts for logging purposes. One of the attributes I want to log is message ID from rabbit MQ.
We are using the following object:
namespace MassTransit
{
public interface ConsumeContext<out T> : ConsumeContext, MessageContext, PipeContext, IPublishEndpoint, IPublishObserverConnector, ISendEndpointProvider where T : class
{
T Message { get; }
/// <summary>Notify that the message has been consumed</summary>
/// <param name="duration"></param>
/// <param name="consumerType">The consumer type</param>
Task NotifyConsumed(TimeSpan duration, string consumerType);
/// <summary>
/// Notify that a fault occurred during message consumption
/// </summary>
/// <param name="duration"></param>
/// <param name="consumerType"></param>
/// <param name="exception"></param>
Task NotifyFaulted(TimeSpan duration, string consumerType, Exception exception);
}
}
It is the generic Message that I need to get hold of within the intercept.
I can successfully cast it to an object say:
ConsumeContext<AuthenticationDataRequest>
And within visual studio once I've cast it the Message object pops up (without casting there is no MessageObject).
To cast I am using the following generic method:
public Guid? RunMessageRetrieve(dynamic obj, Type castTo)
{
MethodInfo castMethod = GetType().GetMethod("GetMessageIdFromContext").MakeGenericMethod(castTo);
return castMethod.Invoke(null, new object[] { obj }) as Guid?;
}
public static Guid? GetMessageIdFromContext<T>(dynamic context) where T : class
{
Guid? messageId = null;
try
{
var contextCasted = (T)context;
Type contextType = contextCasted.GetType();
var message = contextCasted.GetType().GetProperty("Message");
if (message != null)
{
messageId = message.GetType().GetProperty("MessageId").GetValue(message) as Guid?;
}
}
catch (InvalidCastException castException)
{
Console.WriteLine("Could not retrieve message Id from context message as the cast failed");
}
catch (NullException nullException)
{
Console.WriteLine("Could not retrieve message Id from context as the message Id did not exist");
}
return messageId;
}
Here you can see in visual studio the message, and within that I can get the message ID:
However I have tried to get the actual message property out using reflection because of course I don't know the type at compile time and I just can't seem to work it out. The following is null because it's of course a generic type:
var message = contextCasted.GetType().GetProperty("Message");
This has to be doable because when the actual method is invoked after the intercepts it has the proper object with the message.