Оригинальный вопрос
Я попытался создать общий класс для своих веб-запросов.
internal class Request<TRequest, TResponse>
where TRequest : class
where TResponse : class
{
public Uri RequestUri;
public TRequest RequestItem;
public TResponse ResponseItem;
...
}
Типы TRequest
и TResponse
используются для сериализации и десериализации с помощью XML, JSON и т. д.
Теперь я хочу сохранить эти Request<>
в списке для постановки в очередь, кэширования и обработки ошибок. Итак, я попытался объявить:
private List<Request<object, object>> requests;
Но тогда я не могу ничего добавить в этот список запросов, потому что когда я пытаюсь:
var a = new Request<FooRequest, BarResponse>();
requests.Add(a);
Я получил:
не может преобразовать из
My.Services.Request<FooRequest,BarResponse>
вMy.Services.Request<object,object>
Есть ли способ иметь типизированный список смешанных типизированных запросов (Request<a,b>
и Request<c,d>
)? Или лучший подход, чтобы справиться с этим?
Я кодирую для .NET 4.5 (Windows Phone, Магазин Windows).
Первое редактирование
После множества комментариев, пары неудовлетворительных ответов и двойного голосования я рассмотрю ниже то, что я пробовал на основе всего этого:
- #P10# #P11# #P12#
#P13#
#P14##P15#
Использование
abstract class BaseRequest
Почти такая же проблема, мой базовый класс не может иметь поле типа
TRequest
илиTResponse
; как получить два варианта? Мне нужно бросить элемент списка. Так чтоList<object>
было бы так же хорошо.Использование универсальных подстановочных знаков
Не существует и, вероятно, никогда не будет.
Проверка ковариации C#
Слишком расплывчатый ответ дан и ничего для его достижения. Нет даже ссылки на MSDN. Я явно говорю о
List<>
, который является ковариантным типом. Решить этот вопрос не так просто, как man google.Проверка цепочки: общий список анонимных классов
Абсолютно не дубликат, так как вопросы/ответы не предназначены для хранения в типизированном поле/свойстве:
var list = new[] { a }.ToList();
Это просто
List<Request<TRequest, TResponse>>
и, к сожалению, я не могу объявить что-либо с типомvar
в классе вне метода.- #P25# #P26# <блочная цитата> #P27# блочная цитата>
Проверка потока: C# — несколько универсальных типов в одном список
Это становится ближе к моей проблеме.
-> Интересно, Saeb сделал тот же комментарий, что и у меня относительно большинства ответов с все то же самое, что и
List<object>
-> Теперь Брайан Уоттс, набравший наименьшее количество голосов из всех ответов, нашел интересный способ получить
TRequest
иTResponse
. Он объявил это в интерфейсе/базовом классе:Type DataType { get; } object Data { get; }
Это решает проблему «как получить варианты».
Первый вывод
Поскольку мне нужно будет получить варианты, мне нужно будет реализовать некоторые Type RequestType
и Type ResponseType
. Это означает, что часть <TRequest,TResponse>
будет бесполезна. Это означает, что я буду использовать только List<Request>
, а ответ на мой вопрос Stackoverflow: нет, вы не можете использовать/выгодно хранить List<Class<T>>
в C#.
Второе редактирование
Мне не удалось реализовать решение Брайана Уоттса: по-видимому, невозможно использовать тип времени выполнения для универсальных методов. Поэтому я не могу написать Deserialize<request.RequestDataType, request.ResponseDataType>(request)
. Итак, я застрял: если я добавляю свои запросы в список запросов, у меня есть типы времени выполнения, и я больше не могу использовать общие методы. Я не знал, что универсальные методы настолько неудобны. :(
Второй вывод
У меня будет List<Request>
, и каждый Request
будет содержать enum
для типа запроса, затем я включу это перечисление и вручную запишу все возможные вызовы запроса:
switch (@req.RequestType)
{
case RequestType.FirstKindOfRequest:
await Deserialize<FirstKindOfRequest, FirstKindOfResponse>(req);
break;
case RequestType.SecondKindOfRequest:
...
}
К сожалению, это единственный способ, которым я смог найти список Class<T>
, где T
должно было быть чем угодно.
new Request<Foo, Bar>()
вnew Request(Foo, Bar)
. - person Henk Holterman   schedule 23.05.2014Request<TRequest, TResponse>
реализовать некоторый интерфейс, вы можете составить список этого типа интерфейса. Список строго типизирован, поэтому то, что вы хотите, невозможно.Request<T1, T2>
отличается отRequest<T3, T4>
типа - person Dennis_E   schedule 23.05.2014class Request{...}
- person Henk Holterman   schedule 23.05.2014class Request{...}
, то да, вы правы, но вы не включили это изменение в свой комментарий. - person rosko   schedule 23.05.2014get
, а неset
. Принимая во внимание, что реализующее свойство в классе может иметь какget
, так иset
- person Ben Aaronson   schedule 30.06.2014