Ninject problem binding to constant value in MVC3 with a RavenDB session - asp.net-mvc

I've seen a lot of different ways of configuring Ninject with ASP.NET MVC, but the implementation seems to change slightly with each release of the MVC framework. I'm trying to inject a RavenDB session into my repository. Here is what I have that's almost working.
public class MvcApplication : NinjectHttpApplication
{
...
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new MyNinjectModule());
}
public static IDocumentSession CurrentSession
{
get { return (IDocumentSession)HttpContext.Current.Items[RavenSessionKey]; }
}
...
}
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IUserRepository>().To<UserRepository>();
Bind<IDocumentSession>().ToConstant(MvcApplication.CurrentSession);
}
}
When it tries to resolve IDocumentSession, I get the following error.
Error activating IDocumentSession using binding from IDocumentSession to constant value
Provider returned null.
Activation path:
3) Injection of dependency IDocumentSession into parameter documentSession of constructor of type UserRepository
Any ideas on how to make the IDocumentSession resolve?

ToConstant(MvcApplication.CurrentSession) is evaluated at application start. What you want is delayed evaluation ToMethod(ctx => MvcApplication.CurrentSession)

Related

Autofac injection to custom Web-Api FilterAttribute

I have a custom ExceptionFilter that logs all uncaught exceptions inside Web-Api controllers. I would like to use Autofac, to inject ILog configurations to it.
My question is how to do so ? Autofac site has almost no explanation on how to do so.
CustomFilter:
public class ApiControllerErrorFilterAttribute : ExceptionFilterAttribute
{
private static readonly ILog log = LogManager.GetLogger("ApiLog");
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
log.Error("Error: ", actionExecutedContext.Exception);
}
}
p.s.
For clarification, I also have a custom Filter for normal controllers and I was able to successfully configure it.
Filter for normal controllers:
public class ControllerErrorFilterAttribute : HandleErrorAttribute
{
public ICustomLogSettings Log { get; set; }
public override void OnException(ExceptionContext filterContext)
{
Log.GetLogger.Error("Error: ", filterContext.Exception);
}
}
Log Configuration:
builder.Register(c => new BaseLog()).As<ICustomLogSettings>().InstancePerRequest();
builder.RegisterFilterProvider();
Some of these examples may help, especially:
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.Register(c => new MyWebApiFilter())
.AsWebApiActionFilterFor<ValuesController>()
.InstancePerApiRequest();
From that, it shows me that you can register a filter that gets resolved just like any other service, this means you should be able to do:
public class ApiControllerErrorFilterAttribute : ExceptionFilterAttribute
{
private readonly ILog _log
public ApiControllerErrorFilterAttribute(ILog log)
{
_log = log;
}
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
_log.Error("Error: ", actionExecutedContext.Exception);
}
}
And then be able to register it like so:
builder.RegisterType<ApiControllerErrorFilterAttribute>()
.AsWebApiActionFilterFor<ValuesController>()
.InstancePerApiRequest();
Then of course, you need to set up registration for resolving ILog, which will be very similar to this part of the wiki.

Ninject inject dependency from OnApplicationStarted

I'm using a service from my OnApplicationStarted inside my Global.ascx.cs file. Is there a way to dependency inject the repository from there?
My code:
public class MvcApplication : NinjectHttpApplication
{
//Need to dependency inject this.
private IBootStrapService bootService;
protected override void OnApplicationStarted()
{
//Used to set data such as user roles in database on a new app start.
bootService.InitDatabase();
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
internal class SiteModule : NinjectModule
{
public override void Load()
{
//I set my bindings here.
Bind<IBootStrapService>().To<BootStrapService>();
Bind<IUserRepository>().To<SqlServerUserRepository>()
.WithConstructorArgument("connectionStringName", "MyDb");
}
}
}
So how do I get ninject to do DI right inside the app start? As you can see, I setup my bindings in the SiteModule class.
You could override the CreateKernel method where you would register your modules:
protected override IKernel CreateKernel()
{
return new StandardKernel(
new INinjectModule[]
{
new SiteModule()
}
);
}
This will not automatically inject the bootService field though. You could instantiate it like this:
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
//Used to set data such as user roles in database on a new app start.
var bootService = Kernel.Get<IBootStrapService>();
bootService.InitDatabase();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

Ninject doesn't call Dispose on objects when out of scope

I was surprised to find that at least one of my objects created by Ninject is not disposed of at the end of the request, when it has been defined to be InRequestScope
Here's the object I'm trying to dispose:
Interface:
public interface IDataContext : IDisposable
{
MessengerEntities context { get; set; }
}
MessengerEntities is Entity Framework's implementation of ObjectContext -- my context object.
Then I create a concrete class like so:
public class DataContext : IDataContext
{
private MessengerEntities _context = new MessengerEntities();
public MessengerEntities context
{
get
{
return _context;
}
set
{
_context = value;
}
}
#region IDisposable Members
public void Dispose()
{
context.Dispose();
}
#endregion
}
And then I have a Ninject controller factory like so (this is modeled on the Steve Sanderson MVC 2 book):
public class NinjectControllerFactory : DefaultControllerFactory
{
// a Ninject "kernel" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new MessengerServices());
// ASP.NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class MessengerServices : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<DataContext>().InRequestScope();
Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
}
}
}
Now, when I put a breakpoint at the call to context.Dispose() in the DataContext object and run the debugger, that code never gets executed.
So, the evidence suggests that Ninject does not dispose of objects when they go out of scope, but simply creates new objects and relies on the garbage collector to get rid of them at a time of its choosing.
My question is: should I be concerned about this? Because I am -- I would think Ninject would dispose of any object that implements IDisposable.
UPDATE: I downloaded the Ninject Mvc extensions (for MVC 3) and this is now how I'm doing the MvcApplication and the binding, and it does seem to be disposing of my context object.
In global.asax:
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
and
public class EFBindingModule : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<DataContext>().InRequestScope();
Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
}
}
Everything else remains the same.
Ninject will dispose your objects as soon as the request object is collected by the GC. But normally this takes some time. But there is a way to force early disposal after the request ended. The best way is to use Ninject.Web.MVC http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ instead of implementing your own ControllerFactory. The other way is to configure your application to use the OnePerRequestModule.

Implementing UnitOfWork with Castle.Windsor

Simple question.
How do I use UnitOfWork with Castle.Windsor, nHibernate, and ASP.NET MVC?
Now for the extended details. In my quest to understand the UnitOfWork pattern, I'm having difficulty coming across anything that uses a direct example in conjunction with Castle.Windsor, specifically in regards to the way it needs to be installed.
Here is my understanding so far.
IUnitOfWork
The IUnitOfWork interface is used to declare the pattern
The UnitOfWork class must Commit and Rollback transactions, and Expose a Session.
So with that said, here is my IUnitOfWork. (I am using Fluent nHibernate)
public interface IUnitOfWork : IDisposable
{
ISession Session { get; private set; }
void Rollback();
void Commit();
}
So here is my Castle.Windsor Container Bootstrapper (ASP.NET MVC)
public class WindsorContainerFactory
{
private static Castle.Windsor.IWindsorContainer container;
private static readonly object SyncObject = new object();
public static Castle.Windsor.IWindsorContainer Current()
{
if (container == null)
{
lock (SyncObject)
{
if (container == null)
{
container = new Castle.Windsor.WindsorContainer();
container.Install(new Installers.SessionInstaller());
container.Install(new Installers.RepositoryInstaller());
container.Install(new Installers.ProviderInstaller());
container.Install(new Installers.ControllerInstaller());
}
}
}
return container;
}
}
So now, in my Global.asax file, I have the following...
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
// Register the Windsor Container
ControllerBuilder.Current
.SetControllerFactory(new Containers.WindsorControllerFactory());
}
Repository
Now I understand that I need to pass the ISession to my Repository. So then, let me assume IMembershipRepository.
class MembershipRepository : IMembershipRepository
{
private readonly ISession session;
public MembershipRepository(ISession session)
{
this.session = session;
}
public Member RetrieveMember(string email)
{
return session.Query<Member>().SingleOrDefault( i => i.Email == email );
}
}
So I am confused, now. Using this method, the ISession doesn't get destroyed properly, and the UnitOfWork never gets used.
I've been informed that UnitOfWork needs to go in the Web Request Level - but I cannot find anything explaining how to actually go about this. I do not use a ServiceLocator of any sort ( as when I tried, I was told this was also bad practice... ).
Confusion -- How does a UnitOfWork get created?
I just don't understand this, in
general. My thought was that I would
start passing UnitOfWork into the
Repository constructors - but if it
has to go in the Web Request, I'm not
understanding where the two relate.
Further Code
This is extra code for clarification, simply because I seem to have a habit of never providing the right information for my questions.
Installers
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
AllTypes.FromThisAssembly()
.BasedOn<IController>()
.Configure(c => c.LifeStyle.Transient));
}
}
public class ProviderInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<Membership.IFormsAuthenticationProvider>()
.ImplementedBy<Membership.FormsAuthenticationProvider>()
.LifeStyle.Singleton
);
}
}
public class RepositoryInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<Membership.IMembershipRepository>()
.ImplementedBy<Membership.MembershipRepository>()
.LifeStyle.Transient
);
container.Register(
Component
.For<Characters.ICharacterRepository>()
.ImplementedBy<Characters.CharacterRepository>()
.LifeStyle.Transient
);
}
}
public class SessionInstaller : Castle.MicroKernel.Registration.IWindsorInstaller
{
private static ISessionFactory factory;
private static readonly object SyncObject = new object();
public void Install(Castle.Windsor.IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(SessionFactoryFactory)
.LifeStyle.Singleton
);
container.Register(
Component.For<ISession>()
.UsingFactoryMethod(c => SessionFactoryFactory().OpenSession())
.LifeStyle.Transient
);
}
private static ISessionFactory SessionFactoryFactory()
{
if (factory == null)
lock (SyncObject)
if (factory == null)
factory = Persistence.SessionFactory.Map(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["Remote"].ConnectionString);
return factory;
}
}
UnitOfWork
Here is my UnitOfWork class verbatim.
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory sessionFactory;
private readonly ITransaction transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
Session = this.sessionFactory.OpenSession();
transaction = Session.BeginTransaction();
}
public ISession Session { get; private set; }
public void Dispose()
{
Session.Close();
Session = null;
}
public void Rollback()
{
if (transaction.IsActive)
transaction.Rollback();
}
public void Commit()
{
if (transaction.IsActive)
transaction.Commit();
}
}
Your NH Session is a Unit of Work already http://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.aspx
So I'm not sure why you would ever need to abstract this out any further. (if anyone reading this answer know's why I would be happy to hear, I've honestly never heard of any reason why you would need to...)
I would implement a simple Session Per Request. I don't know how you would do that with Windsor since I've never used it, but with It's rather simple with StructureMap.
I wrap the structuremap factory to hold my session factory and inject the session into the repositories as required.
public static class IoC
{
static IoC()
{
ObjectFactory.Initialize(x =>
{
x.UseDefaultStructureMapConfigFile = false;
// NHibernate ISessionFactory
x.ForSingletonOf<ISessionFactory>()
.Use(new SessionFactoryManager().CreateSessionFactory());
// NHibernate ISession
x.For().HybridHttpOrThreadLocalScoped()
.Use(s => s.GetInstance<ISessionFactory>().OpenSession());
x.Scan(s => s.AssembliesFromApplicationBaseDirectory());
});
ObjectFactory.AssertConfigurationIsValid();
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static void ReleaseAndDisposeAllHttpScopedObjects()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
}
In the global.asax file on Request_End I call the ReleaseAndDisposeAllHttpScopedObjects() method.
protected void Application_EndRequest(object sender, EventArgs e)
{
IoC.ReleaseAndDisposeAllHttpScopedObjects();
}
So the session is opened when I call my first repository, and when the request is ended it's disposed of. The repositories have a constructor which takes ISession and assigns it to a property. Then I just resolve the repo like:
var productRepository = IoC.Resolve<IProductRepository>();
Hope that helps. There are many other ways of doing it, this is what works for me.
Is it a linguistic/impedence mismatch issue that the library terms don't jive with the lingo you are familiar with?
I am pretty new to this [fluent] nhibernate, too, so I am still trying to figure it out, but my take is this:
Normally, associate the ISession with an Application session (eg, if it were a web app, you would might consider associating the creation of the session with the Application_Start event, and dispose when the app shuts down -- gracefully or not). When the scope of the app goes away, so should the repository.
The UnitOfWork is just a way of wrapping/abstraction transactions, where you have more than one action to perform during an update, and to remain consistent they must both complete, in sequence, and each successfully. Such as when applying more than trivial business rules to data creation, analysis, or transforms...
Here is a link to a blog post that provides an example of using ISession and UnitOfWork in a fluent style.
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/#comments
EDIT: Just to emphasize, I don't think you -must- use a unit of work for every operation against a repository. The UnitOfWork is only really needed when a transaction is the only reasonably choice, but I am just starting with this, too.

Castle Windsor IoC in an MVC application

Prepare for a wall of code... It's a long read, but it's as verbose as I can get.
In response to Still lost on Repositories and Decoupling, ASP.NET MVC
I think I am starting to get closer to understanding this all.
I'm trying to get used to using this. Here is what I have so far.
Project
Project.Web (ASP.NET MVC 3.0 RC)
Uses Project.Models
Uses Project.Persistence
Project
Project.Models (Domain Objects)
Membership.Member
Membership.IMembershipProvider
Project
Project.Persistence (Fluent nHibernate)
Uses Project.Models
Uses Castle.Core
Uses Castle.Windsor
Membership.MembershipProvider : IMembershipProvider
I have the following class in Project.Persistence
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
namespace Project.Persistence
{
public static class IoC
{
private static IWindsorContainer _container;
public static void Initialize()
{
_container = new WindsorContainer()
.Install(
new Persistence.Containers.Installers.RepositoryInstaller()
);
}
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
}
}
namespace Persistence.Containers.Installers
{
public class RepositoryInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<Membership.IMembershipProvider>()
.ImplementedBy<Membership.MembershipProvider>()
.LifeStyle.Singleton
);
}
}
}
Now, in Project.Web Global.asax Application_Start, I have the following code.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
// Register the Windsor Container
Project.Persistence.IoC.Initialize();
}
Now then, in Project.Web.Controllers.MembershipController I have the following code.
[HttpPost]
public ActionResult Register( Web.Models.Authentication.Registration model)
{
if (ModelState.IsValid)
{
var provider = IoC.Resolve<Membership.IMembershipProvider>();
provider.CreateUser(model.Email, model.Password);
}
// If we got this far, something failed, redisplay form
return View(model);
}
So I am asking first of all..
Am I on the right track?
How can I use Castle.Windsor for my ISessionFactory
I have my SessionFactory working like this ...
namespace Project.Persistence.Factories
{
public sealed class SessionFactoryContainer
{
private static readonly ISessionFactory _instance = CreateSessionFactory();
static SessionFactoryContainer()
{
}
public static ISessionFactory Instance
{
get { return _instance; }
}
private static ISessionFactory CreateSessionFactory()
{
return Persistence.SessionFactory.Map(#"Data Source=.\SQLEXPRESS;Initial Catalog=FluentExample;Integrated Security=true", true);
}
}
}
namespace Project.Persistence
{
public static class SessionFactory
{
public static ISessionFactory Map(string connectionString, bool createSchema)
{
return FluentNHibernate.Cfg.Fluently.Configure()
.Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)))
.ExposeConfiguration(config =>
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config)
.SetOutputFile("Output.sql")
.Create(/* Output to console */ false, /* Execute script against database */ createSchema);
})
.Mappings(m =>
{
m.FluentMappings.Conventions.Setup(x =>
{
x.AddFromAssemblyOf<Program>();
x.Add(FluentNHibernate.Conventions.Helpers.AutoImport.Never());
});
m.FluentMappings.AddFromAssemblyOf<Mapping.MembershipMap>();
}).BuildSessionFactory();
}
So basically, within my Project.Persistence layer, I call the SessionFactory like this..
var session = SessionFactoryContainer.Instance.OpenSession()
Am I even getting close to doing this right? I'm still confused - I feel like the ISessionFactory should be part of Castle.Windsor, but I can't seem to figure out how to do that. I'm confused also about the way I am creating the Repository in the Controller. Does this mean I have to do all of the 'mapping' each time I use the Repository? That seems like it would be very resource intensive.
Firstly some conceptual details. In an ASP.NET MVC application the typical entry point for a page request is a controller. We want the Inversion of Control container to resolve our controllers for us, because then any dependencies that the controllers have can also be automatically resolved simply by listing the dependencies as arguments in the controllers' constructors.
Confused yet? Here's an example of how you'd use IoC, after it is all set up. I think explaining it this way makes things easier!
public class HomeController : Controller
{
// lets say your home page controller depends upon two providers
private readonly IMembershipProvider membershipProvider;
private readonly IBlogProvider blogProvider;
// constructor, with the dependencies being passed in as arguments
public HomeController(
IMembershipProvider membershipProvider,
IBlogProvider blogProvider)
{
this.membershipProvider = membershipProvider;
this.blogProvider = blogProvider;
}
// so taking your Registration example...
[HttpPost]
public ActionResult Register( Web.Models.Authentication.Registration model)
{
if (ModelState.IsValid)
{
this.membershipProvider.CreateUser(model.Email, model.Password);
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
Note that you have not had to do any resolving yourself, you have just specified in the controller what the dependencies are. Nor have you actually given any indication of how the dependencies are implemented - it's all decoupled. It's very simple there is nothing complicated here :-)
Hopefully at this point you are asking, "but how does the constructor get instantiated?" This is where we start to set up your Castle container, and we do this entirely in the MVC Web project (not Persistence or Domain). Edit the Global.asax file, setting Castle Windsor to act as the controller factory:
protected void Application_Start()
{
//...
ControllerBuilder.Current
.SetControllerFactory(typeof(WindsorControllerFactory));
}
...and define the WindsorControllerFactory so that your controllers are instantiated by Windsor:
/// Use Castle Windsor to create controllers and provide DI
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer container;
public WindsorControllerFactory()
{
container = ContainerFactory.Current();
}
protected override IController GetControllerInstance(
RequestContext requestContext,
Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
The ContainerFactory.Current() method is static singleton that returns a configured Castle Windsor container. The configuration of the container instructs Windsor on how to resolve your application's dependencies. So for example, you might have a container configured to resolve the NHibernate SessionFactory, and your IMembershipProvider.
I like to configure my Castle container using several "installers". Each installer is responsible for a different type of dependency, so I'd have a Controller installer, an NHibernate installer, a Provider installer for example.
Firstly we have the ContainerFactory:
public class ContainerFactory
{
private static IWindsorContainer container;
private static readonly object SyncObject = new object();
public static IWindsorContainer Current()
{
if (container == null)
{
lock (SyncObject)
{
if (container == null)
{
container = new WindsorContainer();
container.Install(new ControllerInstaller());
container.Install(new NHibernateInstaller());
container.Install(new ProviderInstaller());
}
}
}
return container;
}
}
...and then we need each of the installers. The ControllerInstaller first:
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
AllTypes
.FromAssembly(Assembly.GetExecutingAssembly())
.BasedOn<IController>()
.Configure(c => c.Named(
c.Implementation.Name.ToLowerInvariant()).LifeStyle.PerWebRequest));
}
}
... and here is my NHibernateInstaller although it is different to yours, you can use your own configuration. Note that I'm reusing the same ISessionFactory instance every time one is resolved:
public class NHibernateInstaller : IWindsorInstaller
{
private static ISessionFactory factory;
private static readonly object SyncObject = new object();
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var windsorContainer = container.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(SessionFactoryFactory));
}
private static ISessionFactory SessionFactoryFactory()
{
if (factory == null)
{
lock (SyncObject)
{
if (factory == null)
{
var cfg = new Configuration();
factory = cfg.Configure().BuildSessionFactory();
}
}
}
return factory;
}
}
And finally you'll want to define your ProvidersInstaller:
public class ProvidersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var windsorContainer = container
.Register(
Component
.For<IMembershipProvider>()
.ImplementedBy<SubjectQueries>())
.Register(
Component
.For<IBlogProvider>()
.ImplementedBy<SubjectQueries>());
// ... and any more that your need to register
}
}
This should be enough code to get going! Hopefully you're still with me as the beauty of the Castle container becomes apparent very shortly.
When you define your implementation of your IMembershipProvider in your persistence layer, remember that it has a dependency on the NHibernate ISessionFactory. All you need to do is this:
public class NHMembershipProvider : IMembershipProvider
{
private readonly ISessionFactory sessionFactory;
public NHMembershipProvider(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
}
Note that because Castle Windsor is creating your controllers and the providers passed to your controller constructor, the provider is automatically being passed the ISessionFactory implementation configured in your Windsor container!
You never have to worry about instantiating any dependencies again. Your container does it all automatically for you.
Finally, note that the IMembershipProvider should be defined as part of your domain, as it is defining the interface for how your domain behaviours. As noted above, the implementation of your domain interfaces which deal with databases are added to the persistence layer.
Avoid using a static IoC class like this. By doing this you're using the container as a service locator, so you won't achieve the full decoupling of inversion of control. See this article for further explanations about this.
Also check out Sharp Architecture, which has best practices for ASP.NET MVC, NHibernate and Windsor.
If you have doubts about the lifecycle of the container itself, see Usage of IoC Containers; specifically Windsor

Resources