Integrating Castle Windsor and NHibernate with WCF
May 18, 2008Up until now, we were using the NHibernate facility of Castle Windsor for managing our NHibernate sessions in WCF. But, we want to have a session-per-request approach as one would use when integrating NHibernate with a regular web application.
Yesterday I did a small spike to figure out how this should work. It turned out to be pretty easy. I used this excellent blog post written by Oran Dennison as my guide.
First I created a class that implemented the IServiceBehavior interface.
public class DIServiceBehavior : IServiceBehavior
{
private readonly ISessionFactory _sessionFactory;
public DIServiceBehavior()
{
_sessionFactory = new Configuration()
.Configure()
.BuildSessionFactory();
XmlConfigurator.Configure(); // Log4Net
}
public void ApplyDispatchBehavior(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach(ChannelDispatcherBase cdb in
serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if(cd != null)
{
foreach(EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider =
new DIInstanceProvider
(serviceDescription.ServiceType,
_sessionFactory);
}
}
}
}
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{ }
public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{ }
}
The SessionFactory is created in the constructor because the ApplyDispatchBehaviour method can be called multiple times (for each endpoint).
The next step is to create an instance provider by creating a class that implements the IInstanceProvider:
public class DIInstanceProvider : IInstanceProvider
{
private const String NHibernateSessionKey =
"NHibernate.Session";
private readonly Type _serviceType;
private IDependencyContainer _dependencyContainer;
private readonly ISessionFactory _sessionFactory;
private ISession _session;
public DIInstanceProvider(Type serviceType,
ISessionFactory sessionFactory)
{
Debug.Assert(null != serviceType,
"null != serviceType");
_serviceType = serviceType;
Debug.Assert(null != sessionFactory,
"null = sessionFactory");
_sessionFactory = sessionFactory;
}
public Object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public Object GetInstance(InstanceContext instanceContext,
Message message)
{
_dependencyContainer = new DependencyContainer();
_session = _sessionFactory.OpenSession();
_dependencyContainer
.AddComponentInstance(NHibernateSessionKey, _session);
return _dependencyContainer.Resolve(_serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext,
Object instance)
{
if(null != _session)
{
_session.Close();
_session = null;
}
if(null != _dependencyContainer)
{
_dependencyContainer.Dispose();
_dependencyContainer = null;
}
}
}
I created a wrapper class around for Castle Windsor named DependencyContainer. The GetInstance method opens a new session using the SessionFactory object we instantiated in the service behavior class. The session object is then registered with Castle Windsor. We can now implement our repositories like this:
public class SomeAggregateRepository
{
private ISession _session;
public SomeAggregateRepository(ISession session)
{
_session = session;
}
public SomeAggregate Get(Int64 id)
{
return _session.Get<SomeAggregate>(id);
}
}
When our service operation has been executed, the NHibernate is released by the ReleaseInstance method. Finishing our example, we need to implement a custom ServiceHost and a ServiceHostFactory:
public class DIServiceHost : ServiceHost
{
public DependencyInjectionServiceHost()
: base()
{ }
public DIServiceHost(Type serviceType,
params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{ }
protected override void OnOpening()
{
Description.Behaviors.Add(new DIServiceBehavior());
base.OnOpening();
}
}
public class DIServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
return new DIServiceHost(serviceType, baseAddresses);
}
}
The custom ServiceHostFactory class can now be used in the ServiceHost file required when doing IIS hosting:
<%@ ServiceHost Language="C#"
Debug="true"
Service="WindsorService.MyWindsorService"
Factory="WindsorService.DIServiceHostFactory"
CodeBehind="MyWindsorService.svc.cs" %>
There is also another way for achieving this that I will be investigating the next week or so using the WCF Integration Facility for Castle Windsor. For some reason it is not available in the current release of the Castle stack so I have to grab it from the trunk.
If you have any thoughts, improvements or suggestions I'm glad to hear them from you, my dear reader. It's the only way I'll ever learn :-).
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