簡體   English   中英

Autofac和自變量:解析為更多派生類型

[英]Autofac and contravariance : resolving to more derived type

我正在編寫通用消息處理程序,需要通過AutoFac獲取各種消息處理程序。 消息處理程序的基本定義是:

public interface IMessageHandler<in TMessage> :
    IMessageHandler
    where TMessage : IMessage
{
    Task<IMessageResult> Handle(TMessage message);
}

我還定義了一個標記器接口,以便可以在AutoFac中輕松注冊它們

public interface IMessageHandler
{
}

樣本消息處理程序為:

public class CreatedEventHandler : IMessageHandler<CreatedEvent>
{
    public Task<IMessageResult> Handle(CreatedEvent message)
    {
        // ...
    }
}

這些都通過Autofac使用以下方式很好地注冊了

builder.RegisterAssemblyTypes(assemblies)
       .Where(t => typeof(IMessageHandler).IsAssignableFrom(t))
       .Named<IMessageHandler>(t => t.Name.Replace("Handler", string.Empty))
       .InstancePerLifetimeScope();

這一切都很好。 但是,當我需要解決處理程序時,我遇到了一個問題

// handler returned is non null and of type marker interface IMessageHandler
var handler = container.Resolve("CreatedEvent");

// This is null. I just can't understand why
var createdEventHander = handler as IMessageHandler<IMessage>;

為什么上面的轉換返回null? 即使在IMessageHandler<>接口中定義了IMessageHandler<>

如何解決適當的處理程序?

謝謝

糟糕!

// Covariance
handler as IMessageHandler<IMessage>;

您的handler具有一個不是IMessage而是IMessage實現的通用參數。 因此,這就是協方差 (您正在泛化一個通用參數)。

由於我不知道您的實際軟件架構,因此無法為您提供解決方案。 至少,您知道為什么整個轉換都為null

可能的解決方案,只需很少的努力...

您的消息處理程序都可以實現IMessageHandler<ConcreteEvent>和新的非通用接口IMessageHandler

public interface IMessageHandler
{
      Task<IMessageResult> Handle(IMessage message);
}

public interface IMessageHandler<TMessage> : IMessageHandler
       where TMessage : IMessage
{
       Task<IMessageResult> Handle(TMessage message);
}

public class CreatedEventHandler : IMessageHandler<CreatedEvent>
{
    public Task<IMessageResult> Handle(CreatedEvent message)
    {
        // ...
    }

    // I would implement the non-generic Handle(IMessage) explicitly
    // to hide it from the public surface. You'll access it when successfully
    // casting a reference to IMessageHandler
    Task<IMessageResult> IMessageHandler.Handle(IMessage message) 
    {
         return Handle((CreatedEvent)message);
    }
}

現在,整個轉換將起作用,因為您的類將顯式實現IMessageHandler<IMessage>

為了避免重復太多,可以實現一個抽象類:

public abstract class MessageHandler<TMessage> : IMessageHandler<TMessage>
       where TMessage : IMessage
{
        public abstract Task<IMessageResult> Handle(TMessage message);

        // I would implement the non-generic Handle(IMessage) explicitly
        // to hide it from the public surface. You'll access it when successfully
        // casting a reference to IMessageHandler
        Task<IMessageResult> IMessageHandler.Handle(IMessage message) 
        {
             return Handle((TMessage)message);
        }
}

最后,您的具體消息處理程序將如下所示:

public class CreatedEventHandler : MessageHandler<CreatedEvent>
{
    public Task<IMessageResult> Handle(CreatedEvent message)
    {
        // ...
    }
}

也就是說,可以將您的類型轉換僅handler as IMessageHandler

暫無
暫無

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

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