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

The post has been migrated, original date 13 Jun 2009. This post continues on from my first post "Repositories and factories - Introduction". In this post we will look at how to create a simple entity using a repository and a factory. To start we need to design the properties that our entity is going to have. We are going to use a simple class called Product, this is going to have just a few properties:
public class Product{
	 public Guid Id { get; internal set; }
	 public string Name { get; set; }
	 public string Description { get; set; }
	 public double Price { get; set; }
}
We now need a way to retrieve Product entities, this is where our factory class comes into use. First we need to create an interface for our factory detailing the methods we want:
public interface IProductFactory
{
	 Product GetProduct(Guid id);
	 System.Collections.Generic.IEnumerable<Product> GetProducts();
}
Now we need to implement the interface in my concrete class. The factory is not responsible for retrieving the data from the data source, this will be handed of to the repository class. The factory will be responsible for building the product entity based on the data returned by the repository. To make the communication between the repository and factory clearer we are going to create an interface for the Product class. The interface makes it clear the repository what properties need to be persisted and returned from storage, this makes it a lot easier when writing a concrete implementation of the repository.
public interface IProduct
{
        string Description { get; set; }
        Guid Id { get; }
        string Name { get; set; }
        double Price { get; set; }
}
With this we can now create the concrete factory class, the factory class calls methods on the IRepository interface which is detailed further down the post, however you can see that each method called on the IRepository interface returns objects of type IProduct. These are then mapped to domain entities using the MapToDomain method:
    public class ProductFactory : InterfaceTest.IProductFactory
    {
        IProductRepository _repository;
        public ProductFactory(IProductRepository repository)
        {
            _repository = repository;
        }
        public Product GetProduct(Guid id)
        {
            IProduct product = _repository.GetProduct(id);
            return MapToDomain(product);
        }
        public IEnumerable<Product> GetProducts()
        {
            IEnumerable<IProduct> products = _repository.GetProducts();
            return MapToDomain(products);
        }
        IEnumerable<Product> MapToDomain(IEnumerable<IProduct> products)
        {
            return products.ToList().Select(x => MapToDomain(x));
        }
        Product MapToDomain(IProduct product)
        {
            if (product == null) return null;
            return new Product()
            {
                Description = product.Description,
                Id = product.Id,
                Name = product.Name,
                Price = product.Price
            };
        }
    }
So we have out factory class that builds our entities for use. Now we need to persist them back to the database. Ideally as we don't want to pass the entity back to the factory to save it, if we did we would have to pass a reference to the factory around our application and this would get messy. If we ensure that when the Product entity is created it requires a reference to the repository it came from then we can added a save method to the entity and persist the entity straight back to the repository, so we need to updated the constructor and add a save method:
    public class Product : InterfaceTest.IProduct
    {
	IProductRepository _repository;
        public Product(IProductRepository repository )
        {
            _repository = repository;
            Id = Guid.NewGuid();
        }
        public void Save(){
            _repository.Save(this);
        }

    }
I then need to update the MapToDomain method in the factory to pass in the repository:
        Product MapToDomain(IProduct product)
        {
            if (product == null) return null;
            return new Product(_repository)
            {
                Description = product.Description,
                Id = product.Id,
                Name = product.Name,
                Price = product.Price
            };
        }
With all this done the IProductRepository should look something like this, I am not going to give any code for a concrete implementation of this interface because the code is pretty straight forward.
public interface IProductRepository{
     void Save(IProduct product);
     IProduct GetProduct(Guid id);
     IEnumerable<IProduct> GetProducts();
}
With all this done we can now use this in our application:
IProductRepository repository = new MemoryRepository();
IProductFactory factory = new ProductFactory(repository);

Product prod = factory.GetProduct(new Guid("{0441907B-45B6-471e-8F7D-A187B81991FC}"));
prod.Name = "box of bananas";
prod.Description = "50 bananas in a large box for a monkey";
prod.Price = 4.5;
prod.Save();
This may seem like a little extra working having the factories and repositories but it will allow for my flexibility later on. You can also make the whole task easier using dependency injection to save you having to write so much code. This post deals with a single entity from a single repository. In the next post I will look at more complex entities that may require multiple repositories.
comments powered by Disqus