Unity 2.0 и обработка IDisposable типов (особенно с PerThreadLifetimeManager)

Я знаю, что подобный вопрос задавался несколько раз (например: здесь , из базового класса LifetimeManager (вместе именуемые сроком службы менеджеры), чтобы контролировать, как он хранит ссылки на экземпляры объектов и как контейнер избавляется от этих экземпляров.

Хорошо, звучит хорошо, поэтому я решил проверить реализацию сборки в менеджерах времени жизни. Мой вывод:

  • TransientLifetimeManager - нет обработки удаления. Контейнер только разрешает экземпляр и не отслеживает его. Вызывающий код отвечает за удаление экземпляра.
  • ContainerControlledLifetimeManager - удаляет экземпляр при удалении диспетчера времени жизни (= при удалении контейнера). Предоставляет одиночный экземпляр, совместно используемый всеми контейнерами в иерархии.
  • HierarchicalLifetimeManager - наследует поведение от ContainerControlledLifetimeManager . Он предоставляет «одиночный» экземпляр для каждого контейнера в иерархии (подконтейнеры).
  • ExternalControlledLifetimeManager - нет обработки удаления. Правильное поведение, поскольку контейнер не является владельцем экземпляра.
  • PerResolveLifetimeManager - нет обработки удаления. В целом он аналогичен TransientLifetimeManager , но позволяет повторно использовать экземпляр для внедрения зависимостей при разрешении всего графа объекта.
  • PerThreadLifetimeManager - никакой обработки удаления, как также описано в MSDN. Кто отвечает за удаление?

Реализация встроенного PerThreadLifetimeManager :

public class PerThreadLifetimeManager : LifetimeManager
{
    private readonly Guid key = Guid.NewGuid();
    [ThreadStatic]
    private static Dictionary values;

    private static void EnsureValues()
    {
        if (values == null)
        {
            values = new Dictionary();
        }
    }

    public override object GetValue()
    {
        object result;
        EnsureValues();
        values.TryGetValue(this.key, out result);
        return result;
    }

    public override void RemoveValue()
    { }

    public override void SetValue(object newValue)
    {
        EnsureValues();
        values[this.key] = newValue;
    }
}

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

Я попытался вручную удалить разрешенный экземпляр в коде и обнаружил другую проблему. Я не могу разорвать инстинс. RemoveValue диспетчера времени жизни пуст - после создания экземпляра его невозможно удалить из статического словаря потока (мне также кажется, что метод TearDown ничего не делает). Итак, если вы вызовете Resolve после удаления экземпляра, вы получите удаленный экземпляр. Я думаю, что это может быть довольно большой проблемой при использовании этого диспетчера времени жизни с потоками из пула потоков.

Как правильно использовать этот диспетчер времени жизни?

Более того, эта реализация часто повторно используется в пользовательских диспетчерах времени жизни, таких как PerCallContext, PerHttpRequest, PerAspNetSession, PerWcfCall и т. Д. Только статический словарь потока заменяется какой-то другой конструкцией.

Также я правильно понимаю, что обработка одноразовых объектов зависит от диспетчера времени жизни? Таким образом, код приложения зависит от используемого диспетчера времени жизни.

Я читал, что в других контейнерах IoC, связанных с временными одноразовыми объектами, обрабатываются подконтейнеры, но я не нашел примера для Unity - его, вероятно, можно было бы обрабатывать с помощью подконтейнера с локальной областью действия и HiearchicalLifetimeManager , но я не знаю, как это сделать.

40
задан Community 23 May 2017 в 12:24
поделиться