Ich habe fast fertig implementiert meine Repository-Muster mit einer IRepository<T>
Schnittstelle, eine NewsRepository
Klasse und eine News
Einheit. Das Problem, auf das ich stieß, war der Versuch, gängige Methoden zu einer Basis-Repository-Klasse zu abstrahieren.Wie Implementieren Repository-Muster mit Schnittstelle, Basis und Beton
Ich konnte keinen Weg finden, die Methode Get in NewsRepository
zu abstrahieren, da sie einen bestimmten Linq-Ausdruck enthält.
Meine Fragen sind:
1) Wie kann ich auf eine Basisklasse abstrakt die public T Get(int id)
Methode bitte? Die einzige Möglichkeit, die ich bisher gemacht habe, besteht darin, Expression<Func<T,bool>>
anstelle eines int zu übergeben, aber dann wird das allgemeine Verhalten nicht wirklich abstrahiert, da jede Unterklasse immer noch einen Ausdruck geben muss, der in jedem Fall fast identisch ist dh n => n.id == id
.
2) Wie gebe ich in die Basisklasse auf die Update-Methode die Unterklasse GetViolations und Kartenmethoden bitte? Ich stelle mir vor, die Lösung ist möglicherweise durch die Verwendung von Delegaten, aber ich konnte nicht die Syntax kompilieren
Dies ist eine vereinfachte Menge des Codes - in der Praxis habe ich eine Save-Methode, die Update und fügt statt nur das Update hier gezeigt.
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();
}
}