This post has been migrated from www.experimentsincode.com, we apologise if some of the images or content is missing

This post has been migrated, original date 20 Jun 2009 Following from my post about repositories and factories I am going to look at a more complex entity. This entity will represent a person who can have multiple address. The entities will look something like this:
    public class Person
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public IEnumerable<Address> Addresses { get; set; }
    }

    public class Address : IAddress
    {
        public Guid Id { get; set; }
        public Guid OwnerId { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string Town { get; set; }
        public string County { get; set; }
        public string PostCode { get; set; }
        public AddressType Type { get; set; }
    }
Assuming we are using a database for persistence I don't want to store the individuals details in the same table as the addresses. Our application may have other class that use the Address class and it makes sense to store these together and keep the database properly normalised. We start by making an interface from the Person class to pass to and from the repository that does not include Addresses.
    public interface IPerson
    {
        Guid Id { get; set; }
        int Age { get; set; }
        string FirstName { get; set; }
        string LastName { get; set; }
    }
We can now update the Person class to inherit this interface and pass in the repository that will be used to persist the Person class:
    public class Person : IPerson
    {
        IPersonRepository _repository;

        public Person(IPersonRepository repository)
        {
            _repository = repository;
        }

	.....
We can quickly create a repository and factory class that will retrieve Person objects for us, I won't show the code here but it is included in the source code at the end of the application. So now we can look at populating the list of addresses. To do this we do exactly the same as we did for the simple element, except we must ensure that there is method on the factory called GetAddresses(Guid ownerId) which returns all the addresses for a given Person ID. You may have noticed that we called the parameter ownerId instead of Person ID, this goes back to the fact that multiple classes may have addresses and uncouples the Address class from the Person class. We also need to update the Address class to accept the repository and create methods to persist the address class. The code for the address interface, factory and repository is exactly the same as our simple entity example so I won't go into to much detail. Now we just need to start putting everything together. Start by updating the PersonFactory to accept the AddressFactory. This will allows use to call the GetAddresses(Guid ownerId) when we populate a Person object.
    public class PersonFactory : IPersonFactory
    {
        IPersonRepository _repository;
        AddressFactory _addressFactory;

        public PersonFactory(IPersonRepository repository, AddressFactory addressFactory )
        {
            _repository = repository;
            _addressFactory = addressFactory;
        }

        ....
We can now modify the MapToDomain method to call
GetAddresses(Guid ownerId)
on the AddressFactory object to populate the address list.
        private Person MapToDomain(IPerson person)
        {
            return new Person(_repository)
            {
                Age = person.Age,
                FirstName = person.FirstName,
                Id = person.Id,
                LastName = person.LastName,
                Addresses = _addressFactory.GetAddresses(person.Id)
            };
        }
With that done we now have a way of creating a Person with Addresses with each piece of information coming from a different storage location. We can now make use of these classes as below:
            IAddressRepository addressRep = new MemoryAddressRepository();
            IPersonRepository personRep = new MemoryPersonRepository();

            AddressFactory addressFact = new AddressFactory(addressRep);
            PersonFactory personFact = new PersonFactory(personRep, addressFact);

            Person somebody = personFact.GetPerson(new Guid("{1BB25355-6ABD-48d3-9FE6-5528C6DAE8E7}"));
            somebody.FirstName = "John";
            //this assumes there is at least one address
            somebody.Addresses.First().Address1 = "32 My House";
            somebody.Addresses.First().Save();
            somebody.Save();
comments powered by Disqus