Репозиторий Factory Класс
public enum RepositoryType
{
ClinicRepository,
MedicationRepository,
PatientRepository,
TreatmentRepository
}
public class ObjectFactory<T>
{
public static IRepository<T> GetRepositoryInstance(RepositoryType type)
{
switch (type)
{
case RepositoryType.ClinicRepository:
return new what ?;
default:
return what ?
}
}
}
public interface IRepository<T>
{
void Add(T item);
void Remove(int id);
void Update(T item);
IList<T> GetAll();
T GetItemById(int id);
}
Я пытаюсь создать класс RepositoryFactory, и я скопировал то, что я сделал до сих пор. Может ли кто-нибудь помочь мне разобраться в этом? Я застрял!
Спасибо заранее
изменить:
Я хочу что-то подобное в конце. Можно ли создать 1 класс репозитория и реализовать что-то вроде
dc.THATOBJECT.insertonsubmit(item)?
public class TreatmentRepository : IRepository<Treatment>
{
public void Add(Treatment item)
{
using (PatientsDataContext dc = new PatientsDataContext())
{
dc.Treatments.InsertOnSubmit(item);
dc.SubmitChanges();
}
}
Ответы
Ответ 1
Простейшая из фабрик просто требует, чтобы ваши типы, полученные из IRepository, имели беззаданные конструкторы.
public class ObjectFactory {
public static TRepository GetRepositoryInstance<T, TRepository>()
where TRepository : IRepository<T>, new() {
return new TRepository();
}
}
Если вам нужны конкретные конструкторы для определенного типа репозитория, вы можете указать объекты как массив объектов и создать их с помощью CreateInstance
public class ObjectFactory {
public static TRepository GetRepositoryInstance<T, TRepository>(
params object[] args)
where TRepository : IRepository<T> {
return (TRepository)Activator.CreateInstance(typeof(TRepository), args);
}
}
Чтобы использовать любой из них, вам просто нужно сказать
var treatmentRepo =
ObjectFactory.GetRepositoryInstance<Treatment, TreatmentRepository>();
Ответ 2
Чтобы что-то вернуть, вам нужно написать класс, который реализует IRepository<T>
.
public class SomeKindOfRepository<T> : IRepository<T>
{
public void Add(T item)
{
}
// and so on...
}
Похоже, что существует четыре разных типа (ClinicRepository, MedicationRepository и т.д.) - они очень разные в том, как они "хранят" вещи? Если да, сделайте отдельный класс для каждого из них. В противном случае используйте один и тот же класс с некоторыми полями для управления его поведением.
Обновление
Основываясь на ваших изменениях и комментариях, у вас есть репозиторий, который действительно является некоторыми операциями в таблице. Единственное, что действительно меняется, - это та таблица, которую она обертывает. Но таблица является членом контекста данных. Таким образом, вы можете отложить выбор таблицы до производного класса.
Это будет базовый класс:
public class GeneralRepository<TEntity, TContext> : IRepository<TEntity>
{
protected abstract Table<TEntity> GetTable(TContext dc);
public void Add(Treatment item)
{
using (TContext dc = new TContext())
{
GetTable(dc).InsertOnSubmit(item);
dc.SubmitChanges();
}
}
// and so on for other methods
}
Производный класс должен указать только, как выбрать таблицу из контекста:
public class TreatmentsRepository : GeneralRepository<Treatment, PatientsDataContext>
{
protected override Table<Treatment> GetTable(PatientsDataContext dc)
{
return dc.Treatments;
}
}
Ответ 3
Вы можете обойтись без enum
. Вам нужен либо общий тип репозитория, либо различные типы репозиториев, реализующие IRepository<T>
. Если вы используете общий репозиторий, вы можете реализовать factory, выполнив что-то в строках:
public class ObjectFactory<T>
{
public static IRepository<T> GetRepositoryInstance()
{
return new Repository<T>();
}
}
Ответ 4
Я бы рекомендовал использовать для этого контейнер Inversion of Control (IoC). В Factory (или вы даже можете перейти прямо к контейнеру IoC), можно получить тип.
public interface IClinicRepository : IRepository<Clinic> {}
public class ObjectFactory
{
public static IRepository<T> GetRepository(RepositoryType type)
{
switch (type)
{
case RepositoryType.ClinicRepository:
return container.Resolve<IClinicRepository>()
default:
throw new NotSupportedException()
}
}
}
или еще лучше. Просто используйте общий метод в factory
public static IRepository<T> GetRepository<T>()
{
return container.Resolve<T>()
}
// to call it
var repository = ObjectFactory.GetRepository<IClinicRepository>();