Autofac - внедренный экземпляр не работает как синглтон

Я регистрирую нужный тип в Autofac как InstancePerLifetimeScope:

builder.RegisterType<WebSecurityContext>()
                .AsSelf()
                .InstancePerLifetimeScope();

и разрешить его через интерфейс:

builder.Register<IApplicationContext>(context =>
            {
                return context.Resolve<WebSecurityContext>();
            })
            .As<IApplicationContext>();

Я ввожу ApplicationContext в свой контроллер WebAPI:

public class MedicalCenterController : BaseApiController
{
    private readonly IApplicationContext applicationContext;

    public MedicalCenterController(IApplicationContext applicationContext)
    {
        this.applicationContext = applicationContext;
    }

ApplicationContext имеет значение MedicalCenterId. Это значение должно измениться после выбора нового медицинского центра в пользовательском интерфейсе.

Изменение MedicalCenterId происходит в фильтре действий, который также содержит необходимый контекст.

public class MedicalCenterAttribute : ActionFilterAttribute
{
    public IApplicationContext ApplicationContext
    {
        get;
        set;
    }

    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        .....
        ApplicationContext.SetMedicalCenterId(medicalCenterId);
    }
}

Но после этого ApplicationContext продолжает иметь прежнее значение MedicalCenterId в MedicalCenterController и других контроллерах.

Почему autofac использует разные экземпляры в разных классах, хотя я использую объект InstancePerLifetimeScope?

Спасибо.


person Artyom Pranovich    schedule 18.08.2014    source источник
comment
Похоже, вы намереваетесь, чтобы MedicalCenterId было значением, связанным с каждым пользователем/сеансом. На самом деле не существует жизненного цикла, связанного с этой концепцией. Если бы это был я, я бы реализовал свой WebSecurityContext, чтобы получить это значение из текущего HttpSession.   -  person Jim Bolla    schedule 18.08.2014


Ответы (1)


Не путайте жизненные области с одиночками. Экземпляры с жизненным циклом будут вести себя аналогично синглтонам, но только в пределах каждого жизненного цикла. Таким образом, зависимые службы, разрешенные из области жизненного цикла, получат один и тот же экземпляр, но службы, разрешенные в другой области жизненного цикла, получат другой экземпляр.

Таким образом, с Autofac в ASP.NET, в дополнение к глобальной/корневой области действия, общей для всего приложения, каждый запрос получает новую область действия. Поскольку контекст приложения в вашем случае зарегистрирован с областью действия, при каждом запросе создается новый контекст приложения. Изменения, внесенные в один экземпляр, видны только службам в рамках одной и той же области действия и будут потеряны, как только запрос будет выполнен.

Так что не путайте жизненные области с синглтонами. Синглтон должен быть зарегистрирован в SingleInstance, а не в InstancePerLifetimeScope.

Обновление: поскольку вы ищете способ установить «идентификатор медицинского центра» для каждого пользователя, это то, что вы не должны обрабатывать внутри Autofac. Мой совет состоит в том, чтобы ApplicationContext загрузить/сохранить это значение в каком-нибудь пользовательском хранилище. Таким образом, всякий раз, когда вы запрашиваете MedicalCenterId, он будет обслуживаться для каждого пользователя, независимо от того, как вы зарегистрируете ApplicationContext в своем контейнере.

person Peter Lillevold    schedule 18.08.2014
comment
Ооо. Спасибо! Но я не могу использовать singleton, потому что в системе много пользователей, и для каждого пользователя должен использоваться другой ApplicationContext. Не могли бы вы дать какой-либо совет или решение этой проблемы? - person Artyom Pranovich; 18.08.2014
comment
@ArtyomPranovich - Понятно. Это не было ясно из вашего вопроса, это указывает на то, что вы хотите, чтобы это был синглтон. Я обновил свой ответ, хотя... - person Peter Lillevold; 19.08.2014