Я пытаюсь создать экземпляры открытого универсального интерфейса репозитория, посредством чего реализации налагают более строгие ограничения типов, чем интерфейс.Каждой реализации интерфейса репозитория требуется конкретная реализация универсального типа для обработки определенных методов / операций на основе свойств переданного типа (для краткости не показаны).
Вот исчерпывающий пример сценария:
public interface IRepository<T> where T : class
{
//...
}
public class BaseRepository<T> : IRepository<T> where T : DbModel
{
//...
}
public class SqlServerDbRepository<T> : BaseRepository<T> where T : SqlServerDbModel
{
//...
}
public abstract class DbModel
{
//...
}
// is further derived by other models
public class SqlServerDbModel : DbModel
{
//...
}
public class User : SqlServerDbModel
{
}
// CLIENT CODE
public static IRepository<T> BuildRepository<T>()
where T : class
{
if (typeof(T) == typeof(SqlServerDbModel)) // "is" keyword will not work here (according to IDE, have not checked)
{
return new SqlServerDbRepository<T>(); // How can T be converted or accepted as an input of type "SqlServerDbModel" (the check already confirms it, so we know it should work)
}
else if (typeof(T) == typeof(DbModel))
{
return new BaseRepository<T>(); // How can T be converted or accepted as an input of type "DbModel" (the check already confirms it, so we know it should work)
}
//... else throw error or just return default...
}
// USAGE
public static void TestBuildRepository()
{
var userRepository = BuildRepository<User>();
}
Сначала я попытался запустить сценарий через контейнер IOC (Castle Windsor на случай, если кому-то интересно), подумав, что он автоматически определит ограничения типов, однако это было невозможно (или, по крайней мере, нет).с тем, как он обрабатывает открытые дженерики и внедрение зависимостей).Я подумал, что мог бы использовать собственную фабрику для построения реализаций интерфейса.
Проблема в строках, соответствующих шаблону return new XYZRepository<T>();
, из-за чего я не уверен, как заставить компилятор c # принять универсальный тип "Tmsgstr "передано ему, зная, что оно полностью удовлетворит ограничение типа.Я уверен, что это можно сделать с помощью размышлений, но я нашел только информацию о том, как создавать методы и свойства, а не общие классы.Как этого достичь?
Я не могу вносить какие-либо изменения в интерфейсы, реализации репозитория или модели ... на тот случай, если кто-нибудь собирается сделать это предложение.