Итак, вам просто нужно как-то передать значение из сессии в ваш репозиторий. На самом деле есть много способов достичь этого.
Одним из способов может быть метод типа Initialize
в вашем классе репозитория (и в вашем интерфейсе репозитория, конечно):
public class SecurityRepository : ISecurityRepository
{
public void Initialize(AppState appState)
{
_userId = appState.userId;
_sessionId = appState.sessionId;
}
// some other methods
}
Тогда вы можете вызвать его в конструкторе контроллера:
public MainController(ISecurityRepository securityRepo)
{
_securityRepo = securityRepo;
_securityRepo.Initialize(Session["appstate"] as AppState);
}
Другой способ - вы можете настроить настройку зависимости в action filter . Просто добавьте какой-нибудь аксессуар:
public class AppStateAccessor
{
public AppState AppState { get; set; }
}
Затем установите его в свой фильтр:
public class RequestScopeDependencySetupFilter : ActionFilterAttribute
{
private readonly IKernel _kernel;
public RequestScopeDependencySetupFilter(IKernel kernel)
{
_kernel = kernel;
}
public override void OnActionExecuted(ActionExecutedContext context)
{
var accessor = _kernel.Get<AppStateAccessor>();
accessor.AppState = context.HttpContext.Session["appstate"] as AppState;
}
}
Затем зарегистрируйте этот фильтр как глобальный:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
var kernel = /* get your IKernel somehow */
filters.Add(new RequestScopeDependencySetupFilter(kernel));
}
И, наконец, используйте его в своем хранилище:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository(AppStateAccessor accessor)
{
_userId = accessor.AppState.userId;
_sessionId = accessor.AppState.sessionId;
}
// some other methods
}
Только не забудьте правильно связать свои зависимости. Ключевым моментом этого метода является то, что ваш AppStateAccessor
экземпляр является временным и находится в области запроса . Ninject (в частности, расширение Ninject.Extensions.ContextPreservation
) позволяет привязать экземпляр объекта в контейнере DI для области запроса:
private static void RegisterServices(IKernel kernel)
{
// bind AppStateAccessor in request scope
kernel.Bind<AppStateAccessor>().ToSelf().InRequestScope();
// transient repository
kernel.Bind<ISecurityRepository>().To<Data.SecurityRepository>();
// other dependencies...
}
И еще один способ. Просто используйте HttpContext.Current
статическое свойство в вашем хранилище:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository()
{
var appState = HttpContext.Current.Session["appstate"] as AppState;
_userId = appState.userId;
_sessionId = appState.sessionId;
}
// some other methods
}
Легко реализовать, но добавить жесткую статическую зависимость в ваш репозиторий - забудьте о модульном тестировании.
Еще один способ (который является комбинацией 2-го и 3-го, спасибо @Nkosi) симулировать этот ответ . Извлечь интерфейс из AppStateAccessor
:
public interface IAppStateAccessor
{
AppState AppState { get; }
}
Затем измените AppStateAccessor
немного:
public class AppStateAccessor
{
public AppState AppState { get; }
= HttpContext.Current.Session["appstate"] as AppState;
}
Затем используйте этот интерфейс в вашем хранилище:
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository(IAppStateAccessor accessor)
{
_userId = accessor.AppState.userId;
_sessionId = accessor.AppState.sessionId;
}
// some other methods
}
На этот раз ваш сервис полностью отделен от HttpContext
и может быть легко протестирован модулем.