#c# #generics #traits
#c# #общие #Трейты
Вопрос:
У меня есть две параллельные иерархии классов, где первая иерархия предназначена для API, а вторая используется на уровне модели. Один и тот же тип имеет одно представление (класс) в каждой иерархии, и я хочу «связать» (подробнее позже) эти два класса, чтобы использовать общие.
API
/
ApiA ApiB
Model
/
ModelA ModelB
Например, как только эта функция
public string DoSomething<APIType> (APIType value) {
получает APIType в качестве аргумента (например, ApiB), я хочу вызвать связанный универсальный метод, который принимает ModelType в качестве аргумента типа (в данном случае ModelB).
Я попробовал что-то похожее на это: общедоступная строка doSomething (значение ApiType), где ModelType: модель, где ApiType: API
Но затем я обнаруживаю, что C # не может выполнять частичный вывод, так что это:
class ApiB : Api<ModelB> {}
ApiB obj;
DoSomething(obj)
не может работать (требуются оба аргумента типа)
Я попытался реализовать что-то похожее на черты C , но это не сработало. Можно было бы использовать только тип, но я делаю это для того, чтобы получить дополнительную проверку компилятора.
Я думаю, это не большая проблема, однако я хотел бы знать, знает ли кто-нибудь решение.
Комментарии:
1. Я чувствую, что если ваш ApiA имеет смысл только с ModelA, тогда он должен подкласс API<ModelA> с конкретной моделью, и не должен быть универсальным
Ответ №1:
Это очень сложный вопрос. Проверьте этот код, я заменил associated generic method
call на универсальный конструктор List
. Комментарий, если есть разница между тем, что вы спросили, и тем, что я понял из вопроса.
class Program
{
public class Model { }
public class ModelB : Model { }
public class Api<T> where T : Model
{
public List<T> CallGenericMethod()
{
return new List<T>();
}
}
public class ApiB: Api<ModelB> { }
public static string DoSomething<T>(Api<T> a) where T : Model
{
var b = a.CallGenericMethod();
return b.GetType().ToString();
}
static void Main(string[] args)
{
ApiB a = new ApiB();
Console.WriteLine(DoSomething(a));
}
}
Редактирование двух типов универсальной версии
public class Api<TApi, TModel> where TApi: Api<TApi, TModel> where TModel : Model
{
public List<TModel> CallGenericMethod()
{
return new List<TModel>();
}
}
public class ApiB: Api<ApiB, ModelB> { }
public static string DoSomething<TApi, TModel>(Api<TApi, TModel> a) where TApi : Api<TApi, TModel> where TModel: Model
{
return new Dictionary<TApi, TModel>().GetType().ToString();
}
Комментарии:
1. Он выполняет свою работу, однако мне придется редактировать Api каждый раз, когда я хочу добавить новый метод, который использует этот тип модели generic, поэтому это не лучшее решение (однако кажется, что оно единственное жизнеспособное в C #)
2. @Clynamen Если
DoSomething
вы вызоветеnew List<T>()
егоList<ModelB>
, он также будет создан.3. Раньше я не понимал, что вы не использовали generic в doSomething для APIType , как в вопросе. Я мог бы попытаться заменить это и использовать простое наследование, как вы это сделали
4. @Clynamen Можно использовать оба типа, но немного уродливее.
5. к сожалению, да (это я хотел сказать ранее о частичном выводе). Кстати, я хотел бы избежать этого, поскольку это сделало бы код действительно запутанным (это будет использоваться несколько раз)