Есть ли распорядитель TransientLifetimeManager - PullRequest
1 голос
/ 05 мая 2011

У меня есть представление WPF с соответствующей ViewModel.Все экземпляры разрешаются через контейнер единиц.Поскольку я использую призму, мне нужно два независимых экземпляра представления, чтобы добавить его в две разные области, в которых зарегистрировано представление.Если я попытаюсь добавить один экземпляр в обе области, я получу

InvalidOperationException: указанный элемент уже является логическим дочерним элементом другого элемента.Сначала отключите его.

, когда представление добавляется во второй регион, поскольку оно уже добавлено в первый регион.

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

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

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

Ответы [ 2 ]

2 голосов
/ 05 мая 2011

То, что вы хотите, звучит как вариант диспетчера ContainerControlledLifetime, который не поддерживает одноэлементный экземпляр, а набор экземпляров.К сожалению, это не один из встроенных менеджеров времени жизни.

Вы можете посмотреть код для ContainerControlledLifetimeManager и увидеть, что это довольно просто.Ваша реализация «SynchronizedGetValue» всегда будет возвращать ноль (сигнализируя контейнеру, что необходимо создать новый экземпляр).Вы можете просто создать подкласс ContainerControlledLifetimeManager и переопределить этот метод.

Я в значительной степени написал его.Я полагаю, я мог бы дать вам код.:)

public class ContainerTrackedTransientLifetimeManager :     
             ContainerControlledLifetimeManager
{
    protected override object SynchronizedGetValue()
    {
        return null;
    }
}

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

public class ContainerTrackedTransientLifetimeManager : 
             SynchronizedLifetimeManager, IDisposable
{
    private ConcurrentCollection<object> values = new ConcurrentCollection<object>();

    protected override object SynchronizedGetValue()
    {
        return null;
    }

    protected override void SynchronizedSetValue(object newValue)
    {
        values.Add(newValue);
    }

    public override void RemoveValue()
    {
        Dispose();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {

         var disposables = values.OfType<IDisposable>();
         foreach(var disposable in disposables)
         {
              disposable.Dispose();
         }
         values.Clear();
    }

Я не уверен, какой из этих ответов правильный.Дайте мне знать, как у вас дела.

1 голос
/ 05 мая 2011

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

Таким образом, когда больше нет ссылки на экземпляр, он будет GCed.* * 1003

...