Integrating Castle Windsor and NHibernate with WCF - Throwing the WCF facility and some Rhino Tools in the mix
July 14, 2008A while ago, I wrote this post about how to integrate Castle Windsor and NHibernate with WCF. Last weekend, I used the WCF integration facility of Castle Windsor to accomplish pretty much the same thing, but with less code. We all want that, now don't we?
As a first step, I created a class that implements the ICallContextInitializer.
public class UnitOfWorkContext : ICallContextInitializer
{
private IUnitOfWork _unitOfWork;
public Object BeforeInvoke(InstanceContext instanceContext,
IClientChannel channel,
Message message)
{
_unitOfWork = UnitOfWork.Start();
return null;
}
public void AfterInvoke(Object correlationState)
{
if(_unitOfWork != null)
{
_unitOfWork.Dispose();
_unitOfWork = null;
}
}
}
Notice that I'm not using the SessionFactory and Session classes of NHibernate directly. Instead, I'm using the UnitOfWork classes of Ayende's most excellent Rhino Tools library.
Next an implementation of the IServiceBehavior interface needs to be created in order to apply the UnitOfWork context to the service operations.
public class UnitOfWorkBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach(var channelDispatcher in
serviceHostBase.ChannelDispatchers)
{
var channelDispatcher = cdb as ChannelDispatcher;
if(null != channelDispatcher)
{
foreach(var endpointDispatcher in
channelDispatcher.Endpoints)
{
foreach(var dispatchOperation in
endpointDispatcher.DispatchRuntime.Operations)
{
dispatchOperation.CallContextInitializers
.Add(new UnitOfWorkContext());
}
}
}
}
}
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{ }
public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{ }
}
So far, nothing really new actually. In my previous post, I needed to create a custom ServiceHost and ServiceHostFactory class. This is now taken care of by the WCF integration facility of Castle Windsor. I'm using IIS hosting, so I need to add the DefaultServiceHostFactory of the facility to the ServiceHost file:
<%@ ServiceHost Language="C#"
Debug="true"
Service="WindsorService.MyWindsorService"
Factory="Castle.Facilities.WcfIntegration.
DefaultServiceHostFactory,
Castle.Facilities.WcfIntegration"
CodeBehind="MyWindsorService.svc.cs" %>
Next, we need to add the facility and the service behavior to the Windsor configuration file:
<facilities>
<facility id="wcf"
type="Castle.Facilities.WcfIntegration.WcfFacility,
Castle.Facilities.WcfIntegration" />
</facilities>
<components>
...
<!-- Service behavior -->
<component id="UnitOfWorkBehavior"
type="WindsorService.Wcf.UnitOfWorkBehavior,
WindsorService"/>
...
</components>
We're almost done. As I also mentioned in my previous post, I have this wrapper class for Castle Windsor named DependencyContainer. The last thing we need to do is register the Windsor container for the WCF integration facility:
public DependencyContainer()
{
_windsorContainer = new WindsorContainer(
new XmlInterpreter());
// For Windsor WCF facility
DefaultServiceHostFactory
.RegisterContainer(_windsorContainer.Kernel);
// For Rhino Commons
IoC.Initialize(_windsorContainer);
}
An instance of the DependencyContainer is now created in the Global.ApplicationStart method:
public class Global : HttpApplication
{
private IDependencyContainer _dependencyContainer;
protected void Application_Start(object sender, EventArgs e)
{
_dependencyContainer = new DependencyContainer();
}
protected void Application_End(object sender, EventArgs e)
{
_dependencyContainer.Dispose();
_dependencyContainer = null;
}
}
Voila, no rocket science there either. We're done. What are we exactly gaining here? The biggest benefit is that we can now add WCF behaviors for other concerns, like exception handling, logging, transactions, etc. by just adding them to the Windsor configuration file.
Now, to round off this post I want to show the usage of the Repository library that can also be found in the Rhino Tools Library. The following needs to be added to the Windsor configuration file:
public class Global : HttpApplication
{
private IDependencyContainer _dependencyContainer;
protected void Application_Start(object sender, EventArgs e)
{
_dependencyContainer = new DependencyContainer();
}
protected void Application_End(object sender, EventArgs e)
{
_dependencyContainer.Dispose();
_dependencyContainer = null;
}
}
Now we can use the Repository class like so:
public IEnumerable<Customer> GetAll()
{
return Repository<Customer>.FindAll(
DetachedCriteria.For(typeof(Customer))
.SetFetchMode("Orders", FetchMode.Eager));
}
public Customer GetFor(String code)
{
return Repository<Customer>.Get(code);
}
These repositories even have support for fetching strategies, which is actually pretty neat.
I'm happy to hear some feedback on this.
Till next time,
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be