Mam prostą klasę, która ma być zwykłym POCO - po prostu przechowuje dane. Z jednym wyjątkiem: zawiera kolekcję notatek. Chcę wczytać tę kolekcję w luźny sposób, aby nie musieć pobierać Notatek na Stronach, które ich nie potrzebują. Kod pośredniczący to:Leniwe ładowanie kolekcji - jak zdobyć przedmioty?
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;
}
}
}
Teraz zastanawiam się, jak przejść dalej. Jest to aplikacja ASP.net MVC i używam Dependency Injection do wstrzykiwania IRepositentów w klasy, które ich potrzebują, na przykład moje kontrolery. Ale ponieważ ta klasa tutaj ma być naprawdę prostym DTO, niechętnie wstrzyknę do niej INOTRepository, także dlatego, że osoba dzwoniąca nie powinna się martwić ani nie przejmować faktem, że jest ona załadowana leniwo.
Tak więc myślę o innej klasie w moim modelu, który posiada INoteRepository.
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);
}
}
To zadziała oczywiście, ale zastanawiam się, czy to jest poprawna architektura? Łączę prosty DTOClass z inną klasą Data Access i być może również z moim mechanizmem DI (ponieważ potrzebuję stworzyć instancję klasy Data Access w programie pobierającym Notatki).
Czy zrobiłbyś to inaczej? Czy jest lepszy sposób na zrobienie tego, pamiętając o tym, że już korzystam z Ninject?
Zgaduję, że nie jest to już POCO lub DTO, ponieważ zawiera teraz logikę, ale to jest w porządku. Chcę, aby pojawił się jak POCO dla rozmówcy zewnętrznego, więc lubię mieć właściwość "Uwagi", a nie metody takie jak "GetNotesForProject" na tej lub innych klasach.
Moje obecne rozwiązanie jest naprawdę brzydkie, ponieważ potrzebuję uzyskać jądro Ninject z mojej aplikacji MvcApplication i użyć go do zakodowania klasy ProjectDataProvider, która pobiera InoteRepository w swoim konstruktorze, aby uniknąć konieczności umieszczania INECO-Receptor gdzieś w moim " DTO "-class:
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;
}
}
Edit: Otwarty bounty. Zignorujmy terminologię "POCO" i "DTO", będę odpowiednio odnawiać. A więc chodzi o to: w jaki sposób powinien wyglądać kod Lazy-Loading w takiej sytuacji i czy powinienem/powinnam unikać przekazywania do komórki MyDTOClass elementu INoteRepository?
To jest najlepsza odpowiedź IMO, dostarcza rozwiązania i nieodłącznie uzależnia swoją klasę DTO od IRepository, jestem pewien, że mam widziałem ten wzór zaimplementowany w sposób wielokrotnego użytku albo jako ILazy lub AbstractLazy . –
Ya .. Myślę, że to dokładnie to robi Lazy w .net 4. –
madaboutcode
Tak, to jest metoda, której również bym użył. Programowanie funkcyjne 4tw. =) –