Ich habe eine einfache Klasse, die ein einfacher POCO sein soll - sie enthält nur Daten. Mit einer Ausnahme: Sie enthält eine Sammlung von Notizen. Ich möchte diese Sammlung nachladen, damit ich die Notizen nicht auf Seiten abrufen muss, die sie nicht benötigen. Der Stub dafür ist dieser:
public class MyDTOClass
{
private ICollection<Note> _notes = null;
public ICollection<Note> Notes
{
get
{
if(_notes == null)
{
// Get an INoteRepository and initialize the collection
}
return _notes;
}
}
}
Jetzt frage ich mich, wie es weitergehen soll. Es ist eine ASP.net MVC-Anwendung und ich verwende Dependency Injection, um die IRepositories in Klassen zu injizieren, die sie benötigen, zum Beispiel meine Controller. Aber da diese Klasse hier ein wirklich einfaches DTO sein soll, zögere ich, ein INoteRepository in sie zu injizieren, auch weil der Aufrufer sich nicht darum kümmern sollte, dass dies faul geladen ist.
Ich denke also daran, eine weitere Klasse in meinem Modell zu haben, die ein INoteRepository enthält.
public class MyDataAccessClass
{
private INoteRepository _noteRepo;
// Inject is part of Ninject and makes sure I pass the correct
// INoteRepository automatically
[Inject]
public MyDataAccessClass(INoteRepository noteRepository)
{
_noteRepo = noteRepository;
}
public IEnumerable<Note> GetNotes(int projectId)
{
return _noteRepo.GetNotes(projectId);
}
}
Das würde natürlich funktionieren, aber ich frage mich, ob dies die richtige Architektur ist? Ich kopple die einfache DTOClass mit einer anderen Data Access-Klasse und möglicherweise auch mit meinem DI-Mechanismus (da ich eine Instanz der Data Access-Klasse im Getter von Notes erstellen muss).
Würden Sie es anders machen? Gibt es eine bessere Möglichkeit, dies zu tun, auch unter Berücksichtigung der Tatsache, dass ich bereits Ninject verwende?
Ich vermute, dass es sich nicht mehr um ein POCO oder DTO handelt, da es jetzt Logik enthält, aber das ist in Ordnung. Ich möchte, dass es erscheinen wie ein POCO für den externen Aufrufer, so dass ich lieber eine Eigenschaft "Notes" als Methoden wie "GetNotesForProject" für diese oder andere Klassen habe.
Meine aktuelle Lösung ist wirklich hässlich, da ich den Ninject-Kernel von meiner MvcApplication erhalten und verwenden müssen, um die ProjectDataProvider-Klasse zu spinnen, die ein INoteRepository in seinem Konstruktor nimmt, um zu vermeiden, dass das INoteRepository irgendwo in meiner "DTO"-Klasse zu setzen:
public ICollection<Note> Notes
{
get
{
if(_notes == null)
{
var app = HttpContext.Current.ApplicationInstance as MvcApplication;
if (app == null)
throw new InvalidOperationException("Application couldn't be found");
var pdp = app.Kernel.Get<ProjectDataProvider>();
_notes = new List<Note>(pdp.GetNotes(Id));
}
return _notes;
}
}
Editar: Eröffnete ein Kopfgeld. Ignorieren wir die Terminologie von "POCO" und "DTO", ich werde entsprechend umformulieren. Es geht also darum: Wie sollte der Lazy-Loading-Code in einer solchen Situation aussehen, und kann/sollte ich die Übergabe von INoteRepository an die MyDTOClass vermeiden?