Я играл с поддержкой DI в ASP.NET MVC RC2.
Я выполнил сеанс на запрос для NHibernate и вам нужно вставить ISession
в мой фильтр действий "Единица работы".
Если я напрямую ссылаюсь на контейнер StructureMap (ObjectFactory.GetInstance) или используйте DependencyResolver для получения экземпляра сеанса, все работает нормально:
ISession Session {
get { return DependencyResolver.Current.GetService<ISession>(); }
}
Однако, если я попытаюсь использовать поставщика фильтра StructureMap
(наследует FilterAttributeFilterProvider
), у меня возникают проблемы с фиксацией транзакции NHibernate в конце запроса.
Как будто ISession
объекты разделяются между запросами. Я часто это вижу, так как все мои изображения загружаются через контроллер MVC, поэтому я получаю 20 или около того сеансов NHibernate, созданных при нормальной загрузке страницы.
Я добавил в свой фильтр действий следующее:
ISession Session {
get { return DependencyResolver.Current.GetService<ISession>(); }
}
public ISession SessionTest { get; set; }
public override void OnResultExecuted(System.Web.Mvc.ResultExecutedContext filterContext) {
bool sessionsMatch = (this.Session == this.SessionTest);
SessionTest вводится с использованием поставщика StructureMap Filter.
Я обнаружил, что на странице с 20 образами "sessionMatch" был ложным для 2-3 запросов.
Конфигурация My StructureMap для управления сеансом выглядит следующим образом:
For<ISessionFactory>().Singleton().Use(new NHibernateSessionFactory().GetSessionFactory());
For<ISession>().HttpContextScoped().Use(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());
В global.asax я вызываю следующее в конце каждого запроса:
public Global() {
EndRequest += (sender, e) => {
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
};
}
Безопасна ли эта конфигурация? Раньше я вводил зависимости в один и тот же фильтр, используя пользовательский IActionInvoker
. Это работало нормально до MVC 3 RC2, когда я начал испытывать проблему выше, поэтому я думал, что попробую использовать поставщик фильтра.
Любая помощь будет оценена.
Я использую NHibernate 3 RC и последнюю версию StructureMap
Update:
Ниже приведены мои реализации DependencyResolver
и FilterAttributeFilterProvider
:
public class StructureMapDependencyResolver : IDependencyResolver {
private readonly IContainer container;
public StructureMapDependencyResolver(IContainer container) {
this.container = container;
}
public object GetService(Type serviceType) {
var instance = container.TryGetInstance(serviceType);
if (instance==null && !serviceType.IsAbstract){
instance = AddTypeAndTryGetInstance(serviceType);
}
return instance;
}
private object AddTypeAndTryGetInstance(Type serviceType) {
container.Configure(c=>c.AddType(serviceType,serviceType));
return container.TryGetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType) {
return container.GetAllInstances(serviceType).Cast<object>();
}
}
public class StructureMapFilterAttributeFilterProvider : FilterAttributeFilterProvider
{
private readonly IContainer container;
public StructureMapFilterAttributeFilterProvider(IContainer container) {
this.container = container;
}
protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
return BuildUp(base.GetControllerAttributes(controllerContext, actionDescriptor));
}
protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
return BuildUp(base.GetActionAttributes(controllerContext, actionDescriptor));
}
private IEnumerable<FilterAttribute> BuildUp(IEnumerable<FilterAttribute> attributes) {
foreach (var attr in attributes)
container.BuildUp(attr);
return attributes;
}
}