Я играл с поддержкой 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 изображениями "sessionsMatch" было ложным для 2-3 запросов.
Моя конфигурация 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, когда у меня возникла проблема, описанная выше, поэтому я подумал, что попробую использовать вместо этого поставщика фильтров.
Любая помощь будет принята с благодарностью.
Я ' m с использованием 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;
}
}