2013-05-29 3 views
0

Мне нужно создать фабрику, которая создает сборщики сообщений и отправителей сообщений. У меня есть три интерфейс:Использование интерфейса с контравариантным типом в качестве возвращаемого типа метода в интерфейсе с ковариантным типом

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. 

Если я T ковариант в IMessageSender, я не могу использовать его в качестве типа аргумент метода.

И мне нужно 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. иметь завод метод, который будет создавать фабрику в соответствии с переданным ей параметром
+0

Зачем вам нужно 'IMessageFactory' быть контравариантным в' T'? –

+0

@BenReich Я обновил свой вопрос, чтобы дать понять. – HiveHicks

+0

Как насчет наличия интерфейсов для 'MessageBuilderFactory ' и 'MessageSenderFactory ' и с инвариантом 'MessageHandlerFactory ', который наследует оба? – supercat

ответ

4

Любые идеи?

IMessageFactory<T> не вариант. Задача решена.

Система, которую вы получили прямо сейчас, не является безопасным по типу, поэтому она не является законной. Вы видите, почему это не безопасно? Предположим, что у вас есть реализация IMessageFactory<Tiger>, которая имеет метод CreateSender, который возвращает IMessageSender<Tiger>. Затем вы можете позвонить Send(new Tiger()), и все будет хорошо.

Если вы можете преобразовать исходный IMessageFactory<Tiger> в IMessageFactory<Animal> - потому что ковариантен - тогда вы можете получить IMessageSender<Animal> из него, а затем вы можете вызвать Send(new Octopus()) но основная реализация помнить занимает тигров.

Компилятор знает, что это может произойти и, следовательно, не позволяет вам скомпилировать вашу программу в первую очередь.

+0

Может быть, вы можете показать мне способ сделать это правильно, рассматривая цели, которые я добавил к моему вопросу? Я пытался сделать эту работу уже 3 часа. – HiveHicks

+0

Я могу сделать IMessageFactory невариантным, но тогда возникает вопрос - как реализовать метод CreateMessageFactory(). – HiveHicks

Смежные вопросы