Singleton на контекст вызова (веб-запрос) в единице

Несколько дней назад у меня была проблема с поточной обработкой ASP.NET. Я хотел иметь одноэлементный объект на веб-запрос. Мне на самом деле нужно это для моей единицы работы. Я хотел инстанцировать единицы работы на веб-запрос так, чтобы карта идентификационных данных была действительна через запрос. Таким образом, я мог использовать МОК для введения моего собственного IUnitOfWork к моим классам репозитория прозрачно, и я мог использовать тот же экземпляр, чтобы запросить и затем обновить мои объекты.

Так как я использую Единицу, я по ошибке использовал PerThreadLifeTimeManager. Я скоро понял, что модель потоков ASP.NET не поддерживает то, чего я хочу достигнуть. В основном это использует пул потоков и перерабатывает потоки, и это означает, что я получаю один UnitOfWork на поток!! Однако то, что я хотел, было одной единицей работы на веб-запрос.

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

Это - моя реализация для PerCallContextLifeTimeManager для единицы:

public class PerCallContextLifeTimeManager : LifetimeManager
{
    private const string Key = "SingletonPerCallContext";

    public override object GetValue()
    {
        return CallContext.GetData(Key);
    }

    public override void SetValue(object newValue)
    {
        CallContext.SetData(Key, newValue);
    }

    public override void RemoveValue()
    {
    }
}

И конечно я использую это для регистрации моей единицы работы в коде, подобном этому:

unityContainer
            .RegisterType(
            new PerCallContextLifeTimeManager(),
            new InjectionConstructor());

Надежда это экономит кому-то немного времени.

45
задан CyclingFreak 8 August 2019 в 17:42
поделиться

1 ответ

Отличное решение, но каждый экземпляр LifetimeManager должен использовать уникальный ключ, а не константу:

private string _key = string.Format("PerCallContextLifeTimeManager_{0}", Guid.NewGuid());

В противном случае, если у вас есть более одного объекта, зарегистрированного в PerCallContextLifeTimeManager, они используют один и тот же ключ для доступа к CallContext, и вы выиграли Я не верну ожидаемый объект.

Также стоит реализовать RemoveValue, чтобы гарантировать очистку объектов:

public override void RemoveValue()
{
     CallContext.FreeNamedDataSlot(_key);
}
25
ответ дан 26 November 2019 в 21:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: