Showing posts with label StructureMap. Show all posts
Showing posts with label StructureMap. Show all posts

Friday, April 09, 2010

NCommon Setup

Today I finally get to a post my friend Dan has been riding me to do for some time. How to setup NCommon and StructureMap with Asp.Net MVC.

Before I get started I want to talk a little about what NCommon is. Simply put, NCommon is a library of commonly used design patterns when developing applications. I took that right from the project website. It was developed by Ritesh Rao. The code can be found at google code. The patterns it implements are as follows...
  1. Unit of Work
  2. Repository using Linq
  3. Validation and business rules
  4. Specification using expressions
  5. Guard class
  6. Utility class
This post wont talk to much about these patterns but future posts will talk about some of them.

So Lets get started.

I will be focusing on the following versions...
ASP.Net MVC version 1.0
StructureMap version 2.5.3
StructureMap Adapter version 1.0
NCommon version 1.0

I plan on updating all version once VS2010 comes out. So there will possibly some differences with the setup if running a later version of ASP.Net MVC.

So my project uses Linq 2 Sql as the backend interface to the database, I could have went with Entity Framework or NHibernate as well since NCommon also supports those as well. While I am at it I did not have to use StructureMap either I could have went with Windsow or Spring or Unity. I just chose StructureMap since I like it best. In the future I might switch to EF 4 or NHibernate with fluent NH but for now I am sticking to Linq 2SQL and StructureMap.

So the first thing you need to do is set up you StructureMap Container and store it in the NCommon.Storage.Store.

In the container setup you need to register some things.


public static Container BuildContainer()
{
Container container = new Container(x =>
{
//ncommon
x.ForRequestedType().CacheBy(InstanceScope.Hybrid).TheDefaultIsConcreteType();
x.ForRequestedType(typeof(IRepository<>)).CacheBy(InstanceScope.Hybrid).TheDefaultIsConcreteType(typeof(LinqToSqlRepository<>));
x.ForRequestedType().CacheBy(InstanceScope.Hybrid).TheDefault.Is.ConstructedBy(
() => new DataModelDataContext(ConfigurationManager.ConnectionStrings["ConnectionStringNameFromWeb.Config"].ConnectionString));


//Other project items here.....
});

container.AssertConfigurationIsValid();
return container;
}


So what is going on here... We create a new StructureMap container and tell it how to create objects when asked for a certain object. the first line we tell the container when asked for IUnitOfWorkFactory we want it to return LinqToSqlUnitOfWorkFactory since I am using Linq2Sql. If I was using EF I would have set it up to return EFUnitOfWorkFactory. The same goes for typeof(Irepository<>) we have it return typeof(LinqToSqlRepository). Finally we tell the container how to create our DataContext.

So How do we call this method. Well in the global.asax.cs file is how.

protected void Application_Start()
{
ConfigureContainer();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory());
LinqToSqlUnitOfWorkFactory.SetDataContextProvider(GetDataContext);
}

private void ConfigureContainer()
{
Container container = StructureMapBootStrapper.BuildContainer();

Store.Application.Set("ApplicationContainer", container);

ServiceLocator.SetLocatorProvider
(
() => new StructureMapServiceLocator(Store.Application.Get ("ApplicationContainer"))
);

}


So as you can see on the app startup we call ConfigureContainer and that method calls our build container and then sets the container on the Store. We then use the ServiceLocator and tell it how to find our newly created container. BTW.... the Service locator is part of the Common Service Locator Library from Microsoft using the StructureMap Adapter.

The Next important thing we need to do is tell MVC how to inject our controllers. If you see in the code above ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory()); This code tells MVC to use a ControllerFactory I created instead of the default. Note the following code will not work in MVC 2.0.


public class IocControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
IController result = null;
if (controllerType != null)
{
try
{
IContainer container = Store.Application.Get("ApplicationContainer");
result = container.GetInstance(controllerType) as Controller;

//result = ObjectFactory.GetInstance(controllerType) as Controller;
}
catch (StructureMapException)
{
System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
throw;

}
}

return result;
}
}


As you can see what we are doing is we are asking the Store for our container and trying to find the requested controller. StructurMap is smart in that if we did not define it in the registry it will try to create it itself using the greasiest constructor.

Finally the last thing we need to set the DataContext on the LinqToSqlUnitOfWorkFactory. again from teh app startup method in the global.asax.cs file we do this LinqToSqlUnitOfWorkFactory.SetDataContextProvider(GetDataContext); where GetDataContext is a property that looks like this


private DataContext GetDataContext()
{
return (DataContext)Store.Application.Get("ApplicationContainer").GetInstance(typeof (DataContext));
}


All it does is ask the store for our container and ask it for the DataContext.

That was how I set up my application to use NCommon. In the next post I will talk more about NCommon and some of the patterns. Stay tuned.

Friday, August 07, 2009

IOC Containers

I know I haven't blogged lately. I have been well busy with other things but now have some time.

I am at a new client and was brought on the project mid stream. I was talking with the "Boss" about unit testing and how some of the application is tightly coupled and how that makes testing a little tough. He mentioned to me that he as planning on introducing some decoupling in the back ends and somehow we got to talking about IOC Containers.

I started talking about StructureMap and he saw value of an IOC Container framework. He asked me to build a prototype, that was a little more advanced than the basic example you see on line using StructureMap, Unity, and CastleWindsor.

I know all the Spring.Net people are going crazy now because we decided not to use spring without even comparing it, but sorry, I have used spring and I already know I like StructureMap better. Since I havent used the other tools, they were included.

The prototype was an n-tier app that used mvc.net in the ui. It had a service and datalayer. the idea was using the same interfaces and services, set up the three containers, turn one on run the app, turn another one on run the app, and so on.

The only changes to the app were in the global.asa file, where we build the containers and setting the controller factory.

So lets talk container setup. I felt the setup was pretty easy with windsor and StructureMap. Unity was a little tougher because setting things like default constructers and life management was not as clear. Luckily there was a wealth of information on the internet for how to do these things. The one thing that I really like about StructureMap is on the container you can call a method to assert that the container is valid. If it fails, it gives you a very clear error message explaing why it was not valid. you can have this check and at runtime it will throw, but better practice is just to wrtie a unit test for this. Unity when set up wrong gave me an error at runtime that was hard to understand and I had to parse throught the error about 2/3 of the way through to find out what item was causing the trouble.

As far as using the containers Unity and Windsor dont give you a static object to get your items like StructureMap does with it's ObjectFactory class. You have to manage the access to Unity and Windsor yourself. That said some will argue that if you use Unity or Windsor you would use it with the CommonServiceLocator library. This library will actually handle the container for you.

After showing the "Boss" the protorype and differences he decided to go with StructureMap. Like I told him any of the three would have worked for us, but StrucutreMap's use of Lamdas, and the added auto mocking features won him over.