Windsor Container ResolveIDictionary
Castle framework is really interesting, but do not forget to checkout current trunk in subversion repository, since it is full of new and exciting features. In a little demo that I’m doing to made a screencast for dotnetmarche community, I show how to structure a simple web page to follow Design For Testability principles, and I made a really basic example of a page with a controller. Since the controller needs to use the session I abstracted the session with an interface
publicinterfaceICustomWebContext {
void AddToSession(String key, Object value);
Object GetFromSession(String key);
void ClearSession();
}
I admit that this is not really an exceptional interface J but it will live only for the sake of my screencast. Using this interface I can abstract the concept of session, so the controller is not forced to run inside a live asp.net application. For the website I plug into controller a simple class that simply stores objects into HttpContext.Current.Session, while for test I can use a simple Dictionary<String, object>. To assemble the object I use Windsor container, since it is lightweight and simple to use, but I need to use the current version in the trunk, since rc2 missed a functionality that I love too much. Here is the problem, page controller has this signature
public Page4Controller(IPageAddition page, ICustomWebContext context) {
it needs an instance of the IPageAddition interface, that abstract the methods of the UI interface and also need a concrete implementation of context. I need to create an instance of the Page4Controller whenever the page needs to perform some operation, and I need to pass the instance of the current page and the context. The page is different at each time while context is a singleton class. First I create a little helper class for Windsor
publicstaticclassIoC {
privatestaticIWindsorContainer _container =
newWindsorContainer(
newXmlInterpreter(newConfigResource(“castle”)));
publicstatic T Resolve<T>() {
return _container.Resolve<T>();
}
publicstatic T Resolve<T>(string name) {
return _container.Resolve<T>(name);
}
publicstatic T Resolve<T>(paramsobject[] values) {
System.Collections.Hashtable arguments = new System.Collections.Hashtable();
for (Int32 I = 0; I < values.Length; I += 2) {
arguments.Add(values[I], values[I + 1]);
}
return _container.Resolve<T>(arguments);
}
}
This is only a matter of convenience, the third resolve method is the interesting one, because it use container.Resolve<>(IDictionary) method, that is able to construct an object and lets the caller pass some of the dependencies. Caller code creates a Page4Controller object in this way.
Page4Controller controller = WebSite.IoC.Resolve<Page4Controller>(“page”, this);
Caller specify that the page argument should be passed the current instance of the page, while all other argument are passed according to the setting in config file.
<component
id=“PageControllerForPage4“
service=“WebLogic3.Page4Controller, WebLogic3“
type=“WebLogic3.Page4Controller, WebLogic3“
lifestyle=“Transient“/>
<component
id=“WebContext“
service=“WebLogic3.ICustomWebContext, WebLogic3“
type=“WebLogic3.StandardWebContext, WebLogic3“
lifestyle=“Singleton“/>
As you can see I specifify that the Page4Controller class has a lifestyle of transient, because I need a fresh controller at each page postback and the ICustomWebContext dependency is satisfied by the StandardWebContext class. With this useful feature, we can use object with mixed dependencies, some of them will be resolved by Windsor according to the configuration file, while some others are resolved directly by the caller.
Alk.