#c# #generics
#c# #обобщения
Вопрос:
У меня есть веб-метод, который вызывает метод в DAL для выполнения процедуры по идентификатору и возвращает объект типа MyData.
[WebMethod]
public MyData GetDataById(int id)
{
DAL myDAL = new DAL();
return myDAL.GetDataById(id);
}
Класс MyData выглядит следующим образом
public class MyData
{
public string Name;
public Data[] DataItems;
}
и класс Data
,
public class Data
{
public string key;
public string value;
}
Теперь это работало нормально до тех пор, пока мы не захотели вернуть немного сложных типов.
Например, DataTable
или, возможно, что-то вроде структуры (или класса), содержащей широту, долготу и значение. Итак, очевидно, что класс Data
не может содержать несколько значений или DataTable. (Он содержит две строки, ключ и значение).
Итак, что я на самом деле хочу, так это чтобы тип был универсальным. Поэтому я изменил его на…
public class MyData<T>
{
public string Name;
public T[] DataItems;
}
Итак, я буду делать что-то подобное внутри myDAL.GetDataById
, потому что тип возвращаемых данных отличается в зависимости от типа.
if (GetTypeOfId(id) == "NormalData")
{
MyData<Data> result = new MyData<Data>();
}
else if (GetTypeOfId(id) == "Map")
{
MyData<MapData> result = new MyData<MapData>();
}
Но мне также нужно указать тип для подписи метода, который, к сожалению, обнаруживается ТОЛЬКО во время выполнения.
Как мне справиться с такой ситуацией?
Я чувствую, что использую дженерики для чего-то, для чего я не должен их использовать.
Или как обычно решается ситуация, когда тип обнаруживается только во время выполнения?
ОБНОВЛЕНИЕ: Наихудшим сценарием является использование разных вызовов веб-служб для получения обычных данных и картографических данных, которых я хотел бы избежать.
Комментарии:
1. Для какого метода вам нужно указать тип? Вы не можете сделать общедоступными MyData<T> GetDataById (идентификатор int)?
2. ДА. Для вызова веб-службы, а также метода в DAL.
3. @Cilvic: У вас действительно может быть общий
WebMethod
?
Ответ №1:
Вы можете использовать дженерики только в тех случаях, когда вы можете указать тип во время компиляции, поэтому я не думаю, что они подходят для вашей ситуации.
Я бы рекомендовал использовать два вызова веб-службы, это самый простой способ справиться с этим.
Если вам действительно нужен только один вызов веб-службы, вы могли бы попросить свой веб-метод просто вернуть байт [] (созданный с помощью BinaryFormatter) или строку (созданную, скажем, с помощью XmlSerializer), а затем десериализовать это на стороне вашего клиента, но это означает, что у вас должны быть одинаковые классы с обеих сторон (или у вас должен быть пользовательский код десериализации), и ваш веб-сервис не может легко использоваться несколькими клиентами.
Ответ №2:
Я не уверен, о чем вы просите, но у меня такое чувство, что использование интерфейса с универсальным методом могло бы помочь вам передавать возвращаемые значения и вызывать для этого универсальный метод GetValue.
Если вы используете IData вместо универсального типа в качестве возвращаемого значения, вы сможете извлечь встроенные данные с помощью ret.GetValue<MyData>()
. И если вы зададите тип при создании Data<T>
, вы также сможете запрашивать его.
Возможно, вы сможете адаптировать следующий фрагмент к вашим потребностям.
public interface IData {
type Type { get; set; }
string Name { get; set; }
T GetValue<T>();
}
public class Data<T> : IData
{
public Type Type { get; set; }
public string Name { get; set; }
public T Value { get; set; }
public Tret GetValue<Tret>() {
return (Tret)(Object)Value;
}
}
Ответ №3:
Ответ был довольно простым и глупым с моей стороны, что я не подумал об этом раньше. Я только что создал родительский класс и заставил Data
и все остальные требуемые классы наследоваться от него.