Architecting business collections with private setter in in service layer
Usually I thought this code is a good design:
Look at the private setter for the collection. So nobody can assign a new collection from outside the schoolclass object.
public class Schoolclass
{
public Schoolclass()
{
Pupils = new List<Pupil>();
}
public int SchoolclassId { get; set; }
public string SchoolclassCode { get; set; }
public List<Pupil> Pupils { get; private set; }
}
Regarding this style my data fetching method does not work anymore:
Service Layer doing calls to the SQLite Data Provider:
BL:
public IEnumerable<Schoolclass> GetAdministrationData()
{
var schoolclasses = adminDataProvider.GetSchoolclassList();
foreach (Schoolclass s in schoolclasses)
{
var pupils = adminDataProvider.GetPupilsBySchoolclassId(s.SchoolclassId);
s.Pupils = pupils;
foreach (Pupil p in pupils)
{
var documents = adminDataProvider.GetDocumentsByPupilId(p.Id);
p.Documents = documents;
}
}
return schoolclasses;
}
If I would have now a private setter the above aggregating would not work.
So d开发者_Go百科o I have another choice? Or should I stick to my loading technic ?
This is an issue of immutability. Your List<Pupil>
property is still mutable, even with a private setter.
I can't set your Pupils property directly:
myclass.Pupils = new List<Pupil>();
... but I can modify it:
var myClass = new SchoolClass();
myClass.Pupils.Add(new Pupil());
Here is a good article discussing different types of immutability in C#:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
Yes you you have loads of options:
Add the pupils to the already created list.
var pupils = adminDataProvider.GetPupilsBySchoolclassId(s.SchoolclassId);
s.Pupils.AddRange(pupils);
foreach (Pupil p in pupils)
{
var documents = adminDataProvider.GetDocumentsByPupilId(p.Id);
p.Documents.AddRange(documents);
}
Note that it is kind of bad form to expose List<T>
- Better to expose Collection<T>
though then you will have to add the items one by one.
If you write you guy like this:
public class Schoolclass
{
public Schoolclass()
{
Pupils = new BindingList<Pupil>();
// binding list descends from Collection<T>
}
public int SchoolclassId { get; set; }
public string SchoolclassCode { get; set; }
public Collection<Pupil> Pupils { get; private set; }
}
Of course there are a 1,000,000 ways and more to write this and the loader. I favor lazy loading myself. Then when you only load them when someone asks for the pupils.
精彩评论