Using Microsft Unity Wire Up a Multi Layer Web Application

Saturday, August 2, 2008

Introduction

If you have looked around recently, you may have noticed the latest craze seems to be the poliferation of the IofC / Dependency Injection frameworks for the .Net framework.  Now with the release of Enterprise Library 4.0, Microsoft has released a their own updated version that I really like, albeit I have used Enterprise Library many years now since the inception of the Data Access application block.  But before I get ahead of myself, I suppose the question should be asked, "why should I use a dependancy container at all?"

Benifets of Dependency Injection

  • Don't talk to strangers!  When I was learning to code this was drilled into me by my mentors.  The idea is that your object should not know anything about any other object.  The technical term is "loose coupling" meaning you should be able to take out one object and replace it with another object and as long as it adheres to the same interface there should not be the need for any code changes any where else in your application.
  • Configurability.  It would be nice that if instead Foo, I now want to talk to FooFoo, I should be ably to just reference a new object and change the configuration to point to that new object.
  • Testabiliy.  I should be able to test all functionality even if the function relys on concrete dependencies such as connection to databases or IO read/writes.  With dependency injection, it is easier to do that because you can mock those object since they are now Interfaces. 
  • Another aspect that I like, especially as some who is responsible for reviewing code, is it forces you make interfaces for all you concrete classes which addresses another OO coding rule and that is you should always reference an interface and not a concreate object.

Model View Presenter Pattern and Unity

Lets get to work and create a simple application.

I will address how Model View Presenter works in another blog but basically the benifet of the pattern is its good way to separate UI from functional code not related to UI.

At any rate I have created a registration webpage, that will take the users info and pass it back several layers to a database or service layer.

   10     <div>

   11         New User Registration

   12         <br />

   13         First Name:

   14         <asp:TextBox ID="txtFirstName" runat="server"></asp:TextBox><br />

   15         Last Name:

   16         <asp:TextBox ID="txtLastName" runat="server"></asp:TextBox><br />

   17         Phone Number:

   18         <asp:TextBox ID="txtPhone" runat="server"></asp:TextBox><br />

   19         Email Address:

   20         <asp:TextBox ID="txtEmail" runat="server"></asp:TextBox>

   21         <br />

   22         <asp:Button ID="Button1" runat="server" Text="Button" />

   23     </div>

To use Unity first lets wire it up to Global.asax page so that when application first loads up it will get the Unity configuration and load into memory and cache it.The next step is to set up the view and the presenter.  On his PNPGuidance site, David Hayden gives a really neat approach to use Generics to inject the View onto the Presenter and vice versa, so I am going to do the same thing here.  The only difference is I am going to register the objects using the configuration file instead through code.  David Hayden also has sample of how to do that here.  With initial base work completed, I now have a view that my registation page can impliment which looks like this.

    8     public interface IRegistrationView

    9     {

   10         string FirstName { get;  }

   11         string LastName { get;  }

   12         string Phone { get;  }

   13         string Email { get;  }

   14 

   15         event EventHandler RegisterClicked;

   16     }

The webpage impliments this interface which I can then pass to the presenter.

   26         #region IRegistrationView Members

   27 

   28         public string FirstName

   29         {

   30             get { return txtFirstName.Text; }

   31         }

   32 

   33         public string LastName

   34         {

   35             get { return txtLastName.Text; }

   36         }

   37 

   38         public string Phone

   39         {

   40             get { return txtPhone.Text; }

   41         }

   42 

   43         public string Email

   44         {

   45             get { return txtEmail.Text; }

   46         }

   47 

   48         public event EventHandler RegisterClicked;

   49 

   50         #endregion

   51 

   52         protected void Button1_Click(object sender, EventArgs e)

   53         {

   54             if (RegisterClicked != null)

   55                 RegisterClicked(this, e);

   56         }

The presenter handles the RegisteredClick event which I can use to pass the user down the chain via dependency injection.  You can see in my presenter code that I am injecting the controller object which is the next object down the chain.  It is assumed that this object would process and validate the data, applying any rules before it would then pass it to service layer.

   13         IProcessUserController controller;

   14 

   15         public RegistrationPresenter(IProcessUserController controller)

   16         {

   17             this.controller = controller;

   18         }

   19 

   20 

   21         public override void OnViewInitialized()

   22         {

   23             base.OnViewInitialized();

   24             this.View.RegisterClicked += new EventHandler(View_RegisterClicked);

   25 

   26         }

   27 

   28         void View_RegisterClicked(object sender, EventArgs e)

   29         {

   30             User user = new User();

   31             user.Email = this.View.Email;

   32             user.FirstName = this.View.FirstName;

   33             user.LastName = this.View.LastName;

   34             user.Phone = this.View.Phone;

   35             controller.RegisterUser(user);

   36         }

 Here is the controller code.  It again injects the service/proxy class in the constructor passing the request further down the chain.

    9     public class ProcessUserController : IProcessUserController

   10     {

   11         private readonly IUserServiceProxy proxy;

   12 

   13 

   14         public ProcessUserController(IUserServiceProxy proxy)

   15         {

   16             //do some logic and other stuff here before passing to the service

   17             this.proxy = proxy;

   18         }

   19 

   20         #region IProcessUserController Members

   21 

   22         public void RegisterUser(UnitySamples.Core.Dto.User user)

   23         {

   24             proxy.InsertUser(user);

   25         }

   26 

   27         #endregion

   28     }

All this magic is happening via the details of the configuration file.  The controller class and the proxy class both are listed in the web.config unity section and when the configuration section is read, Unity determines where to inject what concrete class based on what interface is mapped to what class in the configuration file, and what interface is called for in the contructer of the calling class.

   21   <unity>

   22     <typeAliases>

   23       <!-- Lifetime manager types -->

   24       <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, 

   25           Microsoft.Practices.Unity" />

   26     </typeAliases>

   27     <containers>

   28       <container>

   29         <types>

   30           <!-- Lifetime managers specified using the type aliases -->

   31           <type type= "UnitySamples.Core.Controllers.IProcessUserController, UnitySamples.Core"

   32               mapTo="UnitySamples.Core.Controllers.ProcessUserController, UnitySamples.Core">

   33             <lifetime type="singleton" />

   34           </type>

   35           <type type= "UnitySamples.Core.Service.IUserServiceProxy, UnitySamples.Core"

   36               mapTo="UnitySamples.Core.Service.UserServiceProxy, UnitySamples.Core">

   37             <lifetime type="singleton" />

   38           </type>

   39         </types>

   40       </container>

   41     </containers>

   42   </unity>

 

 

 

comments powered by Disqus