簡體   English   中英

在運行時獲取通用屬性的值

[英]Getting the value of a generic property at run time

我正在使用代理和攔截器進行日志記錄。 我要記錄的屬性之一是Rabbit MQ的消息ID。

我們正在使用以下對象:

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);
    }
}

這是我在攔截中需要掌握的通用消息。

我可以成功地將其轉換為對象:

ConsumeContext<AuthenticationDataRequest>

在Visual Studio中,一旦我將其投射,就會彈出Message對象(不投射就沒有MessageObject)。

要進行投射,我使用以下通用方法:

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;
}

在這里,您可以在Visual Studio中看到消息,在其中我可以得到消息ID:

在此處輸入圖片說明

但是我嘗試使用反射來獲取實際的消息屬性,因為當然我不知道在編譯時的類型,而且似乎無法解決它。 以下為空,因為它當然是通用類型:

var message = contextCasted.GetType().GetProperty("Message");

這必須是可行的,因為在攔截之后調用實際方法時,它具有消息的正確對象。

只需將其轉換為具有所需屬性的接口,然后使用它即可。 不需要反思。

public static Guid? GetMessageId<T>(ConsumeContext<T> input) where T : class
{
    var casted = input as ConsumeContext<IMessage>;
    if (casted == null) return null;
    return casted.Message.MessageId;
}

示例程序:

public class Program
{
    public static Guid? GetMessageId<T>(ConsumeContext<T> input) where T : class
    {
        var casted = input as ConsumeContext<IMessage>;
        if (casted == null) return null;
        return casted.Message.MessageId;
    }
    public static void Main()
    {
        var exampleObject = new MyClass<Message>();
        exampleObject.Message = new Message { MessageId = new Guid("00000001-0002-0003-0004-000000000005") };

        var messageId = GetMessageId(exampleObject);
        Console.WriteLine(messageId.Value);
    }
}

輸出:

00000001-0002-0003-0004-000000000005

如果必須向下轉換,它也可以工作,即,即使T是特定類型的消息,您仍然可以將其強制轉換為公開消息的接口或基類。

    public static void Main()
    {
        var exampleObject = new MyClass<SpecificMessage>();
        exampleObject.Message = new SpecificMessage { MessageId = new Guid("00000001-0002-0003-0004-000000000005") };

        var messageId = GetMessageId(exampleObject);
        Console.WriteLine(messageId.Value);
    }

DotNetFiddle上的完整工作示例

最后,我繼續進行以下工作,請客,我沒想到立即像這樣直接使用Type。 動態參數使事情變得混亂:

public static Guid? GetMessageIdFromContext(object context, Type contextType) 
    {
        Guid? messageId = null;

        try
        {
            var contextProp = contextType.GetProperty("Message");
            if (contextProp != null)
            {
                var message = contextProp.GetValue(context);
                if (message != null)
                {
                    messageId = message.GetType().GetProperty("UniqueId").GetValue(message) as Guid?;
                }

            }
        }
        catch (NullException nullException)
        {
            Console.WriteLine("Could not retrieve message Id from context as the message Id did not exist");
        }

        return messageId;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM