Как передать универсальный класс в качестве параметра неуниверсальному конструктору класса

Предположим, следующий код (пожалуйста, прочитайте мой вопрос в комментариях к коду в финальном классе):

//This is my Generic Class
public class ClientRequestInfo<K, V>
{
    public string Id { get; set; }
    private Dictionary<K, V> parameters;

    public ClientRequestInfo()
    {
        parameters = new Dictionary<K, V>();
    }

    public void Add(K key, V value)
    {
        parameters.Add(key, value);
    }
 }

public class ProcessParameters()
{
    private void CreateRequestAlpha()
    {
        ClientRequestInfo<int, string> info = new ClientRequestInfo<int, string>();
        info.Add(1, "Hello");
        SynchRequest s = new SynchRequest(info);
        s.Execute();
    }
    private void CreateRequestBeta()
    {
        ClientRequestInfo<int, bool> info = new ClientRequestInfo<int, bool>();
        info.Add(1, true);
        SynchRequest s = new SynchRequest(info);
        s.Execute();
    }
}

public class SynchRequest
{
    //What type should I put here?
    //I could declare the class as SynchRequest<K, V> but I don't want
    //To make this class generic.
    private ClientRequestInfo<????,?????> info;
    private SynchRequest(ClientRequestInfo<?????,?????> requestInfo)
    {
        //Is this possible?
        this.info = requestInfo;
    }

    public void Execute()
    {}
}

person Ioannis    schedule 29.09.2009    source источник
comment
Почему вы не хотите использовать общий SynchRequest?   -  person AnthonyWJones    schedule 29.09.2009
comment
Можете ли вы рассказать о том, что бы вы сделали в Execute() с элементом информации? Это может послужить основой для функционально эквивалентного ответа.   -  person joshperry    schedule 29.09.2009
comment
Поскольку класс SynchRequest вызывается другими классами проекта, а целью SynchRequest является запуск службы, а не предоставление какой-либо информации о клиенте. Также есть классы, которые используют SynchRequest и не указывают и не требуют никакой информации о клиенте. Так что это не очень хороший подход к тому, чтобы сделать этот класс универсальным. (У SynchRequest есть еще один пустой конструктор)   -  person Ioannis    schedule 29.09.2009
comment
Метод execute считывает параметры из класса clientRequestInfo и отправляет запрос на сервер. Таким образом, он сериализует класс clientRequestInfo и отправляет его на сервер.   -  person Ioannis    schedule 29.09.2009
comment
Я удивлен, что никто не упомянул Фабричный подход. Создайте статический метод, который действует как именованный конструктор.   -  person nawfal    schedule 21.09.2020


Ответы (4)


Если вы не хотите делать SynchRequestInfo универсальным, можете ли вы создать неуниверсальный базовый класс для ClientRequestInfo? --

public abstract class ClientRequestInfo
{
    public abstract void NonGenericMethod();
}

public class ClientRequestInfo<K, V> : ClientRequestInfo
{
    public override void NonGenericMethod()
    {
        // generic-specific implementation
    }
}

Потом:

public class SynchRequest
{
    private ClientRequestInfo info;

    private SynchRequest(ClientRequestInfo requestInfo)
    {
        this.info = requestInfo;
    }

    public void Execute()
    {
        // ADDED: for example
        info.NonGenericMethod();
    }
}
person Ben M    schedule 29.09.2009
comment
Метод Execute, конечно, должен быть объявлен в базовом классе, если CreateRequestAlpha и CreateRequestBeta должны иметь возможность вызывать его. - person Rob Kennedy; 29.09.2009
comment
Execute является частью SynchRequest, а не ClientRequestInfo. - person Ben M; 29.09.2009

Класс должен быть универсальным, если вам нужны универсальные переменные-члены.

private ClientRequestInfo<????,?????> info;

Является общим членом.

Вы можете использовать необщий базовый класс или интерфейс:

class ClientRequestInfo<K,Y> : IClientRequestInfo

Но в вашем примере ClientRequestInfo не имеет неуниверсальных членов, поэтому интерфейс/базовый класс будет пустым и должен быть приведен к правильной универсальной версии, чтобы в любом случае быть полезным.

person Rex M    schedule 29.09.2009

У вас есть два варианта, если вы не хотите делать SynchRequestInfo универсальным.

  1. Создайте необщий базовый класс, чтобы оба использовали его.
  2. Предоставьте интерфейс для использования, например ISynchInfo, и пусть ваш универсальный класс реализует этот интерфейс.

В этом случае я бы предпочел интерфейсный подход, поскольку в будущем вы можете захотеть синхронизировать другие типы (отдельно от клиентских запросов).

person Reed Copsey    schedule 29.09.2009

Заставьте ClientRequestInfo(K,V) реализовать интерфейс ClientRequestInfo с интерфейсными функциями, которые потребуются SynchRequest.

person Coincoin    schedule 29.09.2009