Я довольно плохо знаком с шаблоном проектирования хранилища, и я зашел в тупик, пытаясь реализовать его в отношении наследования.
Я не уверен, даже если я начал в правильном направлении.
Так что в основном у меня будет абстрактный базовый класс Product, например, с id и imagePath, и у меня будет несколько продуктов, которые наследуются от него.
namespace Common
{
public abstract class Product
{
public int Id { get; set; }
public string ImgPath { get; set; }
}
public class Scale : Product
{
public int AdditionalProperty { get; set; }
}
}
Теперь репозитории выглядят следующим образом:
public class BaseRepository
{
protected TEstEntities1 _dataContext = new TEstEntities1();
public BaseRepository()
{
_dataContext = new TEstEntities1();
}
}
public interface IProductRepository
{
Common.Product Get(int id);
void Add(Common.Product p);
void Update(Common.Product p);
List<Common.Product> ListAll();
}
public class ProductRepository : BaseRepository, IProductRepository
{
public Common.Product Get(int id)
{
throw new NotImplementedException();
}
public void Add(Common.Product p)
{
throw new NotImplementedException();
}
public void Update(Common.Product p)
{
throw new NotImplementedException();
}
public List<Common.Product> ListAll()
{
throw new NotImplementedException();
}
}
Моя проблема заключается в следующем: как интегрировать операции, связанные с масштабированием?Кажется плохой идеей добавить что-то вроде Add (Common.Scale s) в IProductRepository.Кажется плохой идеей увидеть внутри Add (Common.Product p), какой тип продукта я пытаюсь добавить, затем привести к нему, затем добавить.
Я думаю, что если бы я описал эту проблемуТочнее, я хочу повторить как можно меньше кода, чтобы каким-то образом изолировать базовый продукт, добавляющий / удаляющий код в репозитории продукта, и каким-то образом поместить, например, специальный код Scale для добавления / удаления внутри другого класса или метода.
Более тщательный мой подход был такой:
public interface IProductRepository<T> where T : Common.Product
{
T Get(int id);
void Add(T p);
void Delete(T p);
}
public abstract class ProductRepository : BaseRepository
{
protected void Add(Common.Product p)
{
_dataContext.AddToProduct(new Product { Id = p.Id, Image = p.ImgPath });
_dataContext.AcceptAllChanges();
}
protected void Delete(Common.Product p)
{
var c = _dataContext.Product.Where(x => x.Id == p.Id).FirstOrDefault();
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
}
protected Product Get(int id)
{
return _dataContext.Product.Where(x => x.Id == id).FirstOrDefault();
}
}
public class CantarRepository : ProductRepository, IProductRepository<Common.Scale>
{
public void Add(Common.Scale p)
{
base.Add(p);
_dataContext.Scale.AddObject
(new Scale { ProductId = p.Id, AdditionalProperty = p.AdditionalProperty });
_dataContext.AcceptAllChanges();
}
public void Delete(Common.Scale p)
{
var c = _dataContext.Scale.Where(x => x.ProductId == p.Id);
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
base.Delete(p);
}
public new Common.Scale Get(int id)
{
var p = base.Get(id);
return new Common.Scale
{
Id = p.Id,
ImgPath = p.Image,
AdditionalProperty = _dataContext.Scale.Where
(c => c.ProductId == id).FirstOrDefault().AdditionalProperty
};
}
}
К сожалению, этого не хватает по одной причине.Если я использую шаблон фабрики для возврата IProductRepository, и внутри него я создаю экземпляр с IProductRepository, то это не будет работать из-за ковариации и контравариантности, и IProductRepository не может быть одновременно и контравариантным, и ковариантным, а разделение методов на два интерфейса кажется нелогичными громоздко.
Я подозреваю, что мне понадобится шаблон фабрики для возврата интерфейса базового класса, но я также открыт для предложений по этому вопросу.Как я уже сказал, я очень новичок в отношении модели репо.
Мне любопытно, что я делаю неправильно, как я могу решить эту проблему и как я могу реализовать это лучше.
Спасибо.