使用具有逆变类型的接口作为具有协变类型的接口中的方法的返回类型

时间:2013-05-29 16:35:20

标签: c# covariance

我需要创建一个生成消息构建器和消息发送器的工厂。我有三个接口:

public interface IMessageFactory<out T> where T : GenericMessage
{
    IMessageBuilder<T> CreateBuilder();
    IMessageSender<T> CreateSender();
}

public interface IMessageBuilder<out T>
{
    T Build(EmailMessage message);
    T Build(EmailTask task);
}

public interface IMessageSender<in T>
{
    void Send(T message);
}

问题是IMessageFactory不会编译,因为编译器说

Invalid variance: The type parameter 'T' must be contravariantly valid on 'IMessageFactory<T>.CreateSender()'. 'T' is covariant.

如果我在IMessageSender中使用T协变,我不能将它用作方法参数的类型。

我需要T在IMessageFactory中协变,以便做类似的事情:

    public IMessageFactory<GenericMessage> CreateMessageFactory(DispatchService dispatchService)
    {
        if (dispatchService == DispatchService.Service1)
        {
            return new Service1MessageFactory();
        }
        else if (dispatchService == DispatchService.Service2)
        {
            return new Service2MessageFactory();
        }

        return null;
    }

,其中

public class Service1MessageFactory : IMessageFactory<Message<Service1Message>>
{
}

public class Service2MessageFactory : IMessageFactory<Message<Service2Message>>
{
}

public class Message<T> : GenericMessage
{
    public T SpecificMessage { get; private set; }

    public string UserLogin { get; set; }

    public Message(T message, string userLogin)
    {
        SpecificMessage = message;
    }
}

我陷入僵局。有什么想法吗?

UPD。

可能我做错了所以我只会描述我基本上需要的东西,也许你可以给我一些关于如何实现它的提示。

所以,我需要:

  1. 能够为不同类型的消息创建构建器和发件人
  2. 让工厂为每种消息类型创建构建器和发件人
  3. 拥有根据传递给它的参数创建工厂的工厂方法

1 个答案:

答案 0 :(得分:4)

  

有什么想法吗?

使IMessageFactory<T>非变体。问题解决了。

您现在拥有的系统不是类型安全的,这就是为什么它不合法。你明白为什么不安全吗?假设您有IMessageFactory<Tiger>的实现,其方法CreateSender返回IMessageSender<Tiger>。然后,您可以致电Send(new Tiger()),一切都很好。

如果您可以将原始IMessageFactory<Tiger>转换为IMessageFactory<Animal> - 因为它是协变的 - 那么您可以从中获取IMessageSender<Animal>,然后您可以调用{{ 1}}但是底层实现记住只需要老虎

编译器知道这可能发生,因此会阻止您首先编译程序。