Repositories and factories - Creating a more complex entity

Published by on
Tags:

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();

Download: Source Code (.RAR 37.5Kb)

Repositories and factories - Creating a simple entity.

Published by on
Tags:

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.

Safari 4 Cookie Problem

Published by on
Tags:

Today I had a problem with storing cookies in Safari 4, in every other browser (including Safari 3) the cookies would be saved, however in Safari 4 the cookie would not save. The cookie I was trying to save was a CSV list of values like:

	,item1,item2

The list of values started with a comma and this turns out to be the problem. If you have this comma Safari 4 will create the cookie but will not save the data, so you end up with an empty cookie.

How to find the currently executing sublayout in Sitecore

Published by on
Tags:

After my post Sitecore Sublayout Parameters I had a question about how to get the ID of the current sublayout without having to hard code the ID. So here is the code:

   15 public partial class layouts_MySubLayout : System.Web.UI.UserControl

   16 {

   17     private readonly string _layoutSearch = "/sitecore/layout/sublayouts//*/{0}";

   18     protected void Page_Load(object sender, EventArgs e)

   19     {

   20         string className = this.GetType().Name;

   21 

   22         //for this is example I am using a Web Site project.

   23         //This means that when I create any User Control it prefixes with 'layouts_' (directory name)

   24         //and suffixes '_ascx' (file extension) to the compiled class name. These have to be removed

   25         className = className.Replace("_ascx","");

   26         className = className.Replace("layouts_", "");

   27 

   28         Response.Write(string.Format(_layoutSearch, className));

   29 

   30         Sitecore.Data.Items.Item template = Sitecore.Context.Database.SelectSingleItem(

   31             string.Format(_layoutSearch, className)

   32         );

   33 

   34         if (template != null)

   35         {

   36             Response.Write(template.ID);

   37         }

   38         else

   39             Response.Write("Not Found");

   40 

   41     }

   42 }

Couple of things to note:

  • When using a Web Site project you will notice that it prefixes and suffixes extra text to the end of your class name at compile time, this has to be removed.
  • I have also assumed that you have kept the name of the class the same as the name of the template.
  • If you are not using a Web Site project but instead using a Web Applicatiton project you maybe able to remove line 25 and 26; just be sure to remove any namespaces so that you are only left with the class name.
  • The code must be run in a member of the sublayout you are trying to retrieve the ID for otherwise you will get an class name

Scala Operator Magic

Published by on
Tags:

I have been looking a learning Scala and the other day I came across this code example on the Scala site. Initially this took a little time to understand so I thought I would blog what is going on so that I don’t forget and hopefully I save someone else some time.

So the code example I am using is below, it’s a slight modification of the code example found on the Scala site:

    1 object complexOps extends Application {

    2   class Complex(val re: Double, val im: Double) {

    3     def + (that: Complex) =

    4       new Complex(re + that.re, im + that.im)

    5     def - (that: Complex) =

    6       new Complex(re - that.re, im - that.im)

    7     def * (that: Complex) =

    8       new Complex(re * that.re - im * that.im,

    9                   re * that.im + im * that.re)

   10     def / (that: Complex) = {

   11       val denom = that.re * that.re + that.im * that.im   

   12       new Complex((re * that.re + im * that.im) / denom,

   13                   (im * that.re - re * that.im) / denom)

   14           }

   15     override def toString =

   16       re + " "+im

   17   }

   18 }

The code is quite simple, it just allows us to do basic operations on Complex objects. So lets add some code and start to get it working. First we need to define some Complex objects that contain some values, add this code after line 17 in the above example:

   18   var com1 = new Complex(1,2)

   19   var com2 = new Complex(3,4)

Now if we add a line to print out some data to the console:

   20   println(com1+com2)

Now save (as complexOps.scala) and compile this code:



And run it like so:



Ok so how did we get 4.0 and 6.0 as a result? Well lets start by looking at the print line:

   20   println(x+y)

What we are telling Scala to do is to use the add operator on the first Complex object, we are not concatenating the toString methods of each object;  we are calling these lines of code:

    3     def + (that: Complex) =

    4       new Complex(re + that.re, im + that.im)

This tells us that the operator can be applied when the other object is also a Complex object. The other object is stored in the variable "that" and we can now make use of it within the method body. As you can see from the line extract we create a new Complex object that use the sum of the original two objects as it's values.The new complex object is then returned, the final step is then to call the toString method. This as you can see will output the two values of our new Complex object to the screen. Pretty cool.

But thats not the end, we can overload this!!! oh yes. Lets define a second class:

   21   class MoreComplex(val re: double){

   22 

   23   }

As you can see really simple! Ok now on our original object lets add another definition for the add operator below the original add operator:

    2   class Complex(val re: Double, val im: Double) {

    3     def + (that: Complex) =

    4       new Complex(re + that.re, im + that.im)

    5     def + (that: MoreComplex) =

    6       new Complex(re+that.re, im)

Now lets create an instance of more complex and print out the result, adding it one of our original Complex objects:

   30   var com3 = new MoreComplex(5)

   31   println(com1+com3)

Ok lets compile this and see what we get as output:



Excellent the correct result! How awesome. With the example the Complex objectmust be on the left of the operator, if you swap the over you will receive and error because the MoreComplex class does not have any operators defined to handle a Complex object.

Have a play with the code and see what the other operators do!

 

All blogs tagged with 'coding'

Projects

Have you read?

Using Linq to SQL to query Sitecore DB's



Blogs by date