Hallo zusammen,
ich stehe gerade ein wenig auf dem Schlauch...
Ich starte gerade ein neues MVC-Projekt und möchte den Datenzugriff möglichst mit Interfaces entkoppeln. Dazu möchte möchte ich gerne ein generisches Repository als Basisklasse verwenden und davon meine spezifischen Repositories ableiten.
Ich habe dazu mal ein Minimalbeispiel erstellt.
Folgende Interfaces habe ich eingeführt:
public interface IEntityBase
{
int Id { get; set; }
}
public interface IRepositoryBase<T> where T : IEntityBase
{
T FindById(int id);
}
public interface IArtikel : IEntityBase
{
String Name { get; set; }
}
public interface IArtikelRepository : IRepositoryBase<IArtikel>
{
void DoSomething();
}
Daraus habe ich dann folgende Implementierungen erstellt:
public class EntityBase : IEntityBase
{
public int Id { get; set; }
}
public class RepositoryBase<T> : IRepositoryBase<T> where T : IEntityBase
{
public T FindById(int id)
{
// Irgendein Code:
return Activator.CreateInstance<T>();
}
}
public class Artikel : EntityBase, IArtikel
{
public String Name { get; set; }
}
public class ArtikelRepository : RepositoryBase<Artikel>, IArtikelRepository
{
public void DoSomething()
{
Console.WriteLine("...");
}
}
Bei dem ArtikelRepository möchte ich also das IArtikelRepository implementieren, wovon das RepositoryBase aber schon die Methode FindById implementiert.
Ich gebe bei FindById T zurück, was im ArtikelRepository vom Typen Artikel ist. Artikel besitzt das Interface IArtikel - genau das erwartet IArtikelRepository auch.
Ich bekomme bei diesem Konstrukt aber folgende Fehlermeldung:> Fehlermeldung:
"ArtikelRepository" implementiert den Schnittstellenmember "IRepositoryBase<IArtikel>.FindById(int)" nicht. "RepositoryBase<Artikel>.FindById(int)" hat nicht den entsprechenden Rückgabetyp "IArtikel" und kann "IRepositoryBase<IArtikel>.FindById(int)" daher nicht implementieren.
Mir ist schon klar, dass IArtikelRepository als Rückgabewert ein "IArtikel" erwartet, ich aber ein "Artikel" zurückgebe. Aber Artikel ist doch IArtikel?! Ich bin etwas verwirrt...
Kann mich jemand aufklären? 😃
public interface IRepositoryBase<T> where T : class, IEntityBase
{
T FindById(int id);
}
public class ArtikelEntity : IEntityBase
{
public String Name { get; set; }
}
public interface IArtikelRepository : IRepositoryBase<ArtikelEntity>
{
void DoSomething();
}
public class ArtikelRepository : RepositoryBase<ArtikelEntity>
{
public void DoSomething()
{
}
}
Kein Overengineering notwendig 😉
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Okay, Danke 😃
Dein 2. Hinweis hat mich zum Ziel gebracht.
Ich bin davon ausgegangen dass es durchaus Sinn ergibt, auch die Entities zu entkoppeln, da ich Service -und Datenzugriffsschicht eigentlich trennen wollte. So könnte eine Entität aus einer Datenbank durchaus mehr oder weniger Eigenschaften benötigen als z.B. Entitäten aus einer OPC-Schnittstelle.
Aber darüber mache ich mir dann Gedanken
Trotzdem wäre das eine Schichtverletzung, weil Du dann die Interfaces durchreichen würdest, was Dich stark bindet.
Es wäre mehr als ungewöhnlich, dass Dein Artikel in allen Schichten gleich aussieht.
Verwende pro Schicht eigene Modelle (Entities > Models > ViewModels) und übertrage deren Werte mit Hilfe von Mappern.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code