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
Related
I'm trying to implement IoC in my windows form application. My choice fell on Simple Injector, because it's fast and lightweight. I also implement unit of work and repository pattern in my apps. Here is the structure:
DbContext:
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model:
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository:
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService:
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
In Member Form I only add a textbox to input member name and a button to save to database. This is the code in member form:
frmMember:
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
I implement the SimpleInjector (refer to http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) in Program.cs as seen in the code below:
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
When I run the program and add a member, it doesn't save to database. If I changed container.Register to container.RegisterSingle, it will save to database. From the documentation, RegisterSingle will make my class to be a Singleton. I can't using RegisterLifeTimeScope because it will generate an error
"The registered delegate for type IMemberService threw an exception. The IUnitOfWork is registered as 'Lifetime Scope' lifestyle, but the instance is requested outside the context of a Lifetime Scope"
1) How to use SimpleInjector in Windows Form with UnitOfWork & Repository pattern?
2) Do I implement the patterns correctly?
The problem you have is the difference in lifestyles between your service, repository, unitofwork and dbcontext.
Because the MemberRepository has a Singleton lifestyle, Simple Injector will create one instance which will be reused for the duration of the application, which could be days, even weeks or months with a WinForms application. The direct consequence from registering the MemberRepository as Singleton is that all dependencies of this class will become Singletons as well, no matter what lifestyle is used in the registration. This is a common problem called Captive Dependency.
As a side note: The diagnostic services of Simple Injector are able to spot this configuration mistake and will show/throw a Potential Lifestyle Mismatch warning.
So the MemberRepository is Singleton and has one and the same DbContext throughout the application lifetime. But the UnitOfWork, which has a dependency also on DbContext will receive a different instance of the DbContext, because the registration for DbContext is Transient. This context will, in your example, never save the newly created Member because this DbContext does not have any newly created Member, the member is created in a different DbContext.
When you change the registration of DbContext to RegisterSingleton it will start working, because now every service, class or whatever depending on DbContext will get the same instance.
But this is certainly not the solution because having one DbContext for the lifetime of the application will get you into trouble, as you probably already know. This is explained in great detail in this post.
The solution you need is using a Scoped instance of the DbContext, which you already tried. You are missing some information on how to use the lifetime scope feature of Simple Injector (and most of the other containers out there). When using a Scoped lifestyle there must be an active scope as the exception message clearly states. Starting a lifetime scope is pretty simple:
using (ThreadScopedLifestyle.BeginScope(container))
{
// all instances resolved within this scope
// with a ThreadScopedLifestyleLifestyle
// will be the same instance
}
You can read in detail here.
Changing the registrations to:
var container = new Container();
container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
container.Register<IMemberRepository, MemberRepository>(Lifestyle.Scoped);
container.Register<IMemberService, MemberService>(Lifestyle.Scoped);
container.Register<DbContext, MemberContext>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
and changing the code from btnSaveClick() to:
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
using (ThreadScopedLifestyle.BeginScope(container))
{
var memberService = container.GetInstance<IMemberService>();
memberService.Save(member);
}
}
is basically what you need.
But we have now introduced a new problem. We are now using the Service Locator anti pattern to get a Scoped instance of the IMemberService implementation. Therefore we need some infrastructural object which will handle this for us as a Cross-Cutting Concern in the application. A Decorator is a perfect way to implement this. See also here. This will look like:
public class ThreadScopedMemberServiceDecorator : IMemberService
{
private readonly Func<IMemberService> decorateeFactory;
private readonly Container container;
public ThreadScopedMemberServiceDecorator(Func<IMemberService> decorateeFactory,
Container container)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Save(List<Member> members)
{
using (ThreadScopedLifestyle.BeginScope(container))
{
IMemberService service = this.decorateeFactory.Invoke();
service.Save(members);
}
}
}
You now register this as a (Singleton) Decorator in the Simple Injector Container like this:
container.RegisterDecorator(
typeof(IMemberService),
typeof(ThreadScopedMemberServiceDecorator),
Lifestyle.Singleton);
The container will provide a class which depends on IMemberService with this ThreadScopedMemberServiceDecorator. In this the container will inject a Func<IMemberService> which, when invoked, will return an instance from the container using the configured lifestyle.
Adding this Decorator (and its registration) and changing the lifestyles will fix the issue from your example.
I expect however that your application will in the end have an IMemberService, IUserService, ICustomerService, etc... So you need a decorator for each and every IXXXService, not very DRY if you ask me. If all services will implement Save(List<T> items) you could consider creating an open generic interface:
public interface IService<T>
{
void Save(List<T> items);
}
public class MemberService : IService<Member>
{
// same code as before
}
You register all implementations in one line using Batch-Registration:
container.Register(typeof(IService<>),
new[] { Assembly.GetExecutingAssembly() },
Lifestyle.Scoped);
And you can wrap all these instances into a single open generic implementation of the above mentioned ThreadScopedServiceDecorator.
It would IMO even be better to use the command / handler pattern (you should really read the link!) for this type of work. In very short: In this pattern every use case is translated to a message object (a command) which is handled by a single command handler, which can be decorated by e.g. a SaveChangesCommandHandlerDecorator and a ThreadScopedCommandHandlerDecorator and LoggingDecorator and so on.
Your example would then look like:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public class CreateMemberCommand
{
public string MemberName { get; set; }
}
With the following handlers:
public class CreateMemberCommandHandler : ICommandHandler<CreateMemberCommand>
{
//notice that the need for MemberRepository is zero IMO
private readonly IGenericRepository<Member> memberRepository;
public CreateMemberCommandHandler(IGenericRepository<Member> memberRepository)
{
this.memberRepository = memberRepository;
}
public void Handle(CreateMemberCommand command)
{
var member = new Member { Name = command.MemberName };
this.memberRepository.Insert(member);
}
}
public class SaveChangesCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratee;
private DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
And the form can now depend on ICommandHandler<T>:
public partial class frmMember : Form
{
private readonly ICommandHandler<CreateMemberCommand> commandHandler;
public frmMember(ICommandHandler<CreateMemberCommand> commandHandler)
{
InitializeComponent();
this.commandHandler = commandHandler;
}
private void btnSave_Click(object sender, EventArgs e)
{
this.commandHandler.Handle(
new CreateMemberCommand { MemberName = txtName.Text });
}
}
This can all be registered as follows:
container.Register(typeof(IGenericRepository<>),
typeof(GenericRepository<>));
container.Register(typeof(ICommandHandler<>),
new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ThreadScopedCommandHandlerDecorator<>),
Lifestyle.Singleton);
This design will remove the need for UnitOfWork and a (specific) service completely.
I think I'm missing something very simple and maybe just need a new set of eyes. I have an ASP.NET MVC application. In that app, I am using Unity for my IoC to handle dependency injection. Each of my repositories need to have a database factory injected into it and each database factory needs to have a principal injected into it. So far, I've been utilizing the PerRequestLifetimeManager to register these.
//Repositories
container.RegisterType<ChatMessageRepository>(new PerRequestLifetimeManager());
container.RegisterType<SignalRConnectionRepository>(new PerRequestLifetimeManager());
//Context
container.RegisterType<IPrincipal, Principal>(new PerRequestLifetimeManager());
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager());
container.RegisterType<UnitOfWork>(new PerRequestLifetimeManager());
Logically, I've tried to register my Hub in the same fashion.
container.RegisterType<ChatHub>(new PerRequestLifetimeManager());
However, whenever I run my app and navigate away from my chat page, I get a "Resolution of the dependency failed" exception and the InnerException tells me "Operation is not valid due to the current state of the object." I've also tried using the default (Transient), PerResolve, and ContainerControlled lifetime Unity managers when registering these guys and cannot seem to get resolve my issue.
Could someone just provide me some demo code with how you used Unity in an ASP.NET MVC application to handle dependency injection into your signalr hubs?
Here's where Unity will inject parameters into my SignalR Hub
public class ChatHub : Hub
{
private readonly ChatMessageRepository _chatMessageRepository;
private readonly SignalRConnectionRepository _signalRConnectionRepository;
private readonly UnitOfWork _unitOfWork;
public ChatHub(ChatMessageRepository chatMessageRepository,
SignalRConnectionRepository signalRConnectionRepository,
UnitOfWork unitOfWork)
{
_chatMessageRepository = chatMessageRepository;
_signalRConnectionRepository = signalRConnectionRepository;
_unitOfWork = unitOfWork;
} ... }
Thanks!
Do it in 3 steps
First. Create UnityHubActivator class
public class UnityHubActivator : IHubActivator
{
private readonly IUnityContainer _container;
public UnityHubActivator(IUnityContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.Resolve(descriptor.HubType);
}
}
Second. Create Unity container and register your dependency resolver before run Startup class
unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);
Third. Use it in your Hub
public class MyHub : Hub
{
public MyHub(Logger logger)
{
logger.Info("hub constructor");
}
}
Note. I do not change anything in my Startup class
There's a trick to do that. You will need to do something like this:
container.RegisterType< ChatHub >(new InjectionFactory(CreateChatHub));
......
and then create a private method CreateChatHub
private static object CreateChatHub(IUnityContainer container)
{
return new ChatHub();
}
1 Create "UnitySignalRDependencyResolver.cs"
public class UnitySignalRDependencyResolver : DefaultDependencyResolver
{
protected IUnityContainer Container;
private bool IsDisposed = false;
public UnitySignalRDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container.CreateChildContainer();
}
/// <summary>
/// Gets the Autofac implementation of the dependency resolver.
/// </summary>
public static UnitySignalRDependencyResolver Current
{
get { return GlobalHost.DependencyResolver as UnitySignalRDependencyResolver; }
}
public override object GetService(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.Resolve(serviceType);
}
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.ResolveAll(serviceType);
}
return base.GetServices(serviceType);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (IsDisposed)
{
return;
}
if (disposing)
{
Container.Dispose();
}
IsDisposed = true;
}
}
2.Add your resolver to Owin pipeline
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Get container
IUnityContainer container = UnityConfig.Container;
// Create resolver
var resolver = new UnitySignalRDependencyResolver(container);
// Create SignalR Configuration
var config = new HubConfiguration
{
Resolver = resolver
};
// Start SignalR
app.Map("/signalr", map =>
{
map.RunSignalR(config);
});
}
}
3.Inject your dependency in your controller's constructor
public class ValuesController : ApiController
{
private readonly IMyDependency _myDependency;
public ValuesController(IMyDependency myDependency)
{
_myDependency= myDependency;
}
}
I'm using MVC4 and Unity 2.1. My services require a service key based on credentials retrieved from session state.
I register my service(s) like so:
container.RegisterType<IInventoryService, InventoryService>();
The constructor for InventoryService is equally simple:
public InventoryService(ServiceKey serviceKey) { ... }
In my website when I've needed a service I use a service locator that automatically composes the service key using credentials from session.
public static T Resolve<T>(ServiceKey serviceKey = null)
{
if (serviceKey == null)
{
serviceKey = SessionManager.ServiceKey;
}
var parameterOverride = new ParameterOverride(SERVICEKEY_PARAMETERNAME, serviceKey);
return Resolve<T>(null, parameterOverride);
}
This has worked well. The problem is that I'm now converting my site to MVC and attempting to inject services into controllers using a simple dependency resolver that uses my exiting service locator (dependency factory):
public class CustomDependencyResolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
return MvcDependencyFactory.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return MvcDependencyFactory.ResolveAll(serviceType);
}
}
My controller looks like:
public InventoryController(IInventoryService inventoryService) { ... }
The problem is that MVC still complains about not finding a parameterless constructor when trying to instantiate the inventory controller. I think this is because I haven't registered a service key in Unity. But if I try doing so, I find that MVC is trying to resolve the controllers, and subsequently the services, before session has even been constructed.
Am I not thinking about this correctly? Each step feels pretty reasonable -- using session credentials in a service, using a service in a controller, using a resolver to help build the controller -- but I've been beating my head against the wall getting this to work.
You can use the InjectionFactory in Unity (Microsoft.Practices.Unity.InjectionFactory) to specify a function to handle the resolution of your dependency. This function will only be executed when the dependency is resolved. In the below example, "c" is your Unity container passed as a argument so that you can do additional resolves within your function.
replace:
container.RegisterType<IInventoryService, InventoryService>();
with:
container.RegisterType<IInventoryService>(new InjectionFactory(c =>
new InventoryService(SessionManager.ServiceKey)));
Using the Unity.Mvc4 package seemed to fix the problem, though it's not clear to me why. But rather than use yet another package and hide away my questions, I decided to add a parameterless constructor that manually resolves itself as necessary:
public InventoryController() : this (MvcDependencyFactory.Resolve<IInventoryService>(SessionManger.ServiceKey) { }
It still allows for unit testing of the controllers (via injection) while being transparent about where the resolution is happening when the parameterless constructor is called.
Below is a custom IDependencyResolver, which was fairly straight forward once I started to dig into how it worked and differed from IoC container resolution. You need the try/catches to capture MVC's attempted resolution of IControllerActivator (source: http://www.devtrends.co.uk/blog/do-not-implement-icontrolleractivator-in-asp.net-mvc-3). If IControllerActivator cannot be resolved, your custom IDependencyResolver will be queried for your controller instead (which will use your IoC container of choice).
I added the below class to my basic MVC4's App_Start folder:
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Sample.Web.Controllers;
namespace Sample.Web.App_Start
{
public static class UnityConfig
{
public static void ConfigureContainer()
{
IUnityContainer container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IHomeService>(new InjectionFactory( c =>
new HomeService("this string is a dependency.")));
container.RegisterType<IController, HomeController>("Home");
return container;
}
}
public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
}
}
Here is my simple controller:
using System.Web.Mvc;
namespace Sample.Web.Controllers
{
public class HomeController : Controller
{
private readonly IHomeService _service;
public HomeController(IHomeService service)
{
_service = service;
}
public ActionResult Index()
{
ViewBag.SomeData = _service.GetSomeData();
return View();
}
}
public interface IHomeService
{
string GetSomeData();
}
public class HomeService : IHomeService
{
private readonly string _data;
public HomeService(string data)
{
_data = data;
}
public string GetSomeData()
{
return _data;
}
}
}
Here is my epically huge view:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>#ViewBag.SomeData</p>
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.
I'm putting the unity container creation/setup in the global.asax. and making the container a static property on that class since i'm not sure how unity works or if the container needs to be kept alive and references elsewhere. What's the recommended location of unity initialization/configuration for mvc 2?
You shouldn't need to keep an explicit reference around for the container. A container should wire up the requested object graph (Controllers in this case) and get out of the way.
Take a look at the container-specific implementations of IControllerFactory in MVCContrib.
That said, I like the WindsorControllerFactory a lot better than the UnityControllerFactory, but you could implement a UnityControllerFactory that uses the same pattern (Constructor Injection) as the WindsorControllerFactory.
If you imagine that we do that, your Global.asax should look like this:
var container = new UnityContainer();
// configure container
var controllerFactory = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
controllerFactory holds a reference to the container, so you can let it go out of scope in Application_Start - it's going to stay around because the ControllerFactory stays around.
Here's how we did it:
public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
}
public static void Configure()
{
IUnityContainer container = new UnityContainer();
//...Register your types here
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return base.GetControllerInstance(requestContext, controllerType);
}
if (!typeof(IController).IsAssignableFrom(controllerType))
{
throw new ArgumentException("Type requested is not a controller", "controllerType");
}
return container.Resolve(controllerType) as IController;
}
}
And then in global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
.... whatever you like
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
UnityControllerFactory.Configure();
}
}