开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜