Я почти завершил реализацию своего шаблона хранилища, имея интерфейс IRepository<T>
, класс NewsRepository
и сущность News
. Проблема, с которой я столкнулся, заключалась в попытке абстрагирования общих методов в базовый класс репозитория.
Я не смог найти способ абстрагировать метод Get в NewsRepository
, поскольку он содержит конкретное выражение Linq.
Мои вопросы :
1) Как мне абстрагироваться от базового класса методом public T Get(int id)
, пожалуйста? Единственный способ, которым я сделал это до сих пор, это передать Expression<Func<T,bool>>
вместо int, но тогда это де-факто не абстрагирует общее поведение, поскольку каждому подклассу все равно нужно будет передать выражение, которое почти идентично каждый случай, т.е. n => n.id == id
.
2) Как передать в базовый класс метода Update подкласс GetViolations и методы map, пожалуйста? Я полагаю, что решение, возможно, заключается в использовании делегатов, но я не смог получить синтаксис для компиляции
Это упрощенный набор кода - на практике у меня есть метод Save, который выполняет обновление и вставку, а не только обновление, показанное здесь.
public interface IRepository<T>
{
T Get(int id);
void Update(T item);
}
public class NewsRepository : IRepository<News>
{
private Table<News> _newsTable;
public NewsRepository(string connectionString)
{
_newsTable = new DataContext(connectionString).GetTable<News>();
}
public News Get(int id)
{
return _newsTable.SingleOrDefault(n => n.NewsId == id);
}
public void Update(News item)
{
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_newsTable.Context.SubmitChanges();
}
private void map(News dbNews, News news)
{
dbNews.Title = news.Title;
dbNews.Article = news.Article;
}
}
public class Repository<T> where T : class
{
protected Table<T> _table;
public Repository(Table<T> t)
{
_table = t;
}
//How do i do this??! - This doesn't compile due to T no having a NewsId
public T Get(int id)
{
return _table.SingleOrDefault(n => n.NewsId == id);
}
//This seems to be a solution, but it's not really abstracting common behaviour as each
//sub-class will still need to pass in the same linq expression...
public T Get(Expression<Func<T,bool>> ex)
{
return _table.SingleOrDefault(ex);
}
public void Update(T item)
{
//How is it possible to pass in the GetRuleViolations and map functions to this method?
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_table.Context.SubmitChanges();
}
}