Using unity for IoC and DI – Part 2 (further decoupling)


This article is an extension of my previous article Using unity for IoC and DI. I would recommend reading that article before start reading this article. However in the previous article I have demonstrated how to install Unity container in a .NET project and how we use that container to decouple our layers; for example Data Access Layer (DAL), Business layer objects (BAL) and presentation layer from each other. Moreover we also have used Dependency Injection (DI) to decouple the DAL layer from the BAL layer so that one can easily replace one DAL layer(i.e SQL DAL) with another(i.e. Oracle DAL).

Fig 1: Objects in the container

In the figure above we can see that there is a partition of “Decoupling Point”. On one side of the partition lies the Service Layer(BAL) objects and interfaces (i.e. IBookService, BookService) and on the other side lies the Data Access Layer(DAL) objects and interfaces (i.e. IBookRepository, BookRepositiry, OracleBookRepository, IBook and Book). And these two layers are decoupled by making BookService  object dependent on IBookRepository, by it’s (BookService) parameterized constructor.

In this above example we have just four objects and three interfaces – as this is mare an example application. But in the real life project you will find hundreds of objects and interfaces which will further increase the demand for replacing and changing the objects more frequently and that’s why we need more decoupling.

So now is time to further decouple these set of objects in our example. But the question is, where we will introduce another decoupling line. Notice in our example that the Model objects (Book and IBook) are used directly in the repository objects (ie. BookRepository and OracleBookRepository). Instead of this direct-use we can introduce dependency in between them. This dependency injection will give you flexibility to replace or modify the Model-objects without breaking the Repository-objects.

Fig2: Objects in the container

To introduce this new dependency injection we modify the constructor of BookRepository and OracleBookRepository so that it depends on a Book interface(ie. IBook).


public class BookRepository : IBookRepository
{
       private IBook book; 
       private List listOfBooks;
       private HomeFinDBEntities db;        
	
       public BookRepository(Ibook bk)
        {
            this.book = bk;
this.db = new HomeFinDBEntities();
            
        }
        
        public Ibook getBookById(int id)
        {
            var result = (from p in db.Books
                         where p.Id == id
                         select p).FirstOrDefault();

            if (result == null)
            {
                return null;
            }
            else
            {
                this.book.BookId = result.Id;
                this.book.BookName = result.Name;
                this.book.BookAuthor = result.Author;
            } 
            return this.book;
        }

        }
 
        … … …
}

By this way we can get a book by id from a DB (ie.e function getBookById(int id)). But what about a list of books? How we can get a list of type IBook (ie. List<IBook>)? My solution in this case is by cloning.  We can clone the object we got from the constructor then we make clones as many as we like, change their individual property value and finally put them in a list; simple isn’t it.

While the cloning involves, the question is which cloning should we use? Deep cloning or shallow cloning? To my investigation shallow cloning is enough – where as it doesn’t involve too much performance overhead.

To make our Book object clone-able we will have to implement the interface ICloneable and then implement clone function.


public interface IBook  : ICloneable
    {      
        string BookAuthor { get; set; }
        int BookId { get; set; }
        string BookName { get; set; }
    }

public class Book : IBook
    {

        public int BookId { get; set; }
        public string BookName { get; set; }
        public string BookAuthor { get; set; }

        public object Clone()
        {
            return (Book)this.MemberwiseClone();            
        }
    }

Now the question is with this shallow cloning will we be able to maintain nested objects in the Book object? For example how are we going to manage a Available-in-Library list (ie. List<ILibrary> AvailableLibs{ get; set; }) in a particular book object, where as a library is a different new object with its own property.


public interface ILibrary: ICloneable
    {
        string LibName { get; set; }
        string Location { get; set; }
    }

public class Library : ILibrary
    {
        public string LibName { get; set; }
        public string Location { get; set; }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

public interface IBook  : ICloneable
    {      

        string BookAuthor { get; set; }
        int BookId { get; set; }
        string BookName { get; set; }
        List AvailableLibs { get; set; }
    }

public class Book :  IBook
    {

        public int BookId { get; set; }
        public string BookName { get; set; }
        public string BookAuthor { get; set; }
        public List AvailableLibs { get; set; }

        public object Clone()
        {
            return (Book)this.MemberwiseClone();            
        }
    }

Simply by shallow cloning we can resolve this problem too. Just implement ICloneable in the Library object as in the code above then make a list of ILibrary in the Book class.

Now create a constructor dependency of BookRepository object on Library object ie. pass a Library object referencing ILibrary while instantiation of BookRepository. Now in the List<Ibook> getBookList() function of BookRepository class, start cloning the Library object that has been passed as dependency. Notice the modified constructor and List<IBook> getBookList() function in the class BookRepository bellow.


public class BookRepository : IBookRepository
    {
        IBook book;
        ILibrary library;
        private List listOfBooks;
        HomeFinDBEntities db;        
        public BookRepository(IBook bk,ILibrary lib)
        {
            this.book = bk;
            this.library = lib;
            this.db = new HomeFinDBEntities();
        }
        
        public IBook getBookById(int id)
        {

            var result = (from p in db.Books
                         where p.Id == id
                         select p).FirstOrDefault();

            if (result == null)
            {
                return null;
            }
            else
            {
                this.book.BookId = result.Id;
                this.book.BookName = result.Name;
                this.book.BookAuthor = result.Author;
                this.library.LibName = result.LibName;
                this.library.Location = result.LibLoc;
                this.book.AvailableLibs = new List();
                this.book.AvailableLibs.Add((ILibrary)this.library);
            }           

            return this.book;
        }

        public List getBookList()
        {
            this.listOfBooks = new List();
            var rsltBoks = from p in db.Books select p;

            foreach (var bok in rsltBoks)
            {
                listOfBooks.Add((IBook)this.book.Clone());
                listOfBooks.Last().BookId = bok.Id;
                listOfBooks.Last().BookName = bok.Name;
                listOfBooks.Last().BookAuthor = bok.Author;
                
                var _libList = new List();
                _libList.Add((ILibrary)this.library.Clone());
                _libList.Last().LibName = bok.LibName;
                _libList.Last().Location = bok.LibLoc;
                listOfBooks.Last().AvailableLibs = _libList;                                                             
            

            }
            return this.listOfBooks;
            
        }

    }

Observe that the shallow cloning is enough to build up a list of objects which have another list of object.

Up to now we have successfully decoupled the Model-Objects (ie. Book and Library) from the Repository-Objects (ie. BookRepository and OracleBookRepository) in code. Now we will have to configure these dependencies in our Unity configuration file unity.config (which we have been following from the previous article Using unity for IoC and DI).

To introduce the dependency of BookRepository class on the Book object configure the BookRepository registration as follow.


<register type="IBookRepository" mapTo="BookRepository" name="SQLrepo" >
  <constructor>
    <param name="bk" dependencyName="BookModel" />
    <param name="lib" dependencyName="LibModel" />
  </constructor>
</register>

So the final unity.config file would be looking like bellow (if you are following from the article Using unity for IoC and DI).



<?xml version="1.0" encoding="utf-8"?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<!-- Models-->
<typeAlias alias="IBook" type="BusinessBackend.IBook, BusinessBackend" />
<typeAlias alias="Book" type="BusinessBackend.Book, BusinessBackend" />
<typeAlias alias="ILibrary" type="BusinessBackend.ILibrary, BusinessBackend" />
<typeAlias alias="Library" type="BusinessBackend.Library, BusinessBackend" />
<!-- Services -->
<typeAlias alias="IBookService" type="BusinessBackend.IBookService, BusinessBackend" />
<typeAlias alias="BookService" type="BusinessBackend.BookService, BusinessBackend" />
<!-- Repositories -->
<typeAlias alias="IBookRepository" type="BusinessBackend.IBookRepository, BusinessBackend" />
<typeAlias alias="BookRepository" type="BusinessBackend.BookRepository, BusinessBackend" />
<typeAlias alias="OracleBookRepository" type="BusinessBackend.OracleBookRepository, BusinessBackend" />
</typeAliases>
<container>
<register type="ILibrary" mapTo="Library" name="LibModel" />
<register type="IBook" mapTo="Book" name="BookModel" />
<register type="IBookRepository" mapTo="BookRepository" name="SQLrepo" >
<constructor>
<param name="bk" dependencyName="BookModel" />
<param name="lib" dependencyName="LibModel" />
</constructor>
</register>
<register type="IBookRepository" mapTo="OracleBookRepository" name="ORACLErepo" >
<constructor>
<param name="bk" dependencyName="BookModel" />
</constructor>
</register>
<register type="IBookService" mapTo="BookService" >
<constructor>
<param name="br" dependencyName="SQLrepo">
<!--<param name="br" dependencyType="BookRepository">-->
<!--<dependency type="BookRepository" />-->
<!--<dependency name="SQLrepo" />-->
</param>
</constructor>
</register>
</container>
</unity>

Finally we can list what we have done so far in this article

  1. Decoupled the Model-objects form the Repository-Objects.
  2. Used shallow cloning while creating a list of Model-objects.
  3. Configure this decoupling in the Unity configuration file.

Comments are appreciated.

Happy coding…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s