IoC Container Unity портит мне жизнь - PullRequest
2 голосов
/ 27 февраля 2011

Возможно, я не понимаю, как это должно работать.

Где я запускаю свое приложение, я делаю это:

IUnityContainer container = new UnityContainer();
container.RegisterInstance<IUnityContainer>(container);

//MainWindow
container.RegisterType<Window, MainWindow>();

//Services
container.RegisterType<IWindowManager, WindowManager>();

//Workspaces
container.RegisterType<WorkspaceViewModel, CompanyWorkspace>("Company");
container.RegisterType<WorkspaceViewModel, DivisionWorkspace>("Division")
//More of this
container.RegisterType<IWorkspaceFactory, WorkspaceFactory>();

Window window = container.Resolve<Window>();
window.DataContext = container.Resolve<ViewModel.MainWindowViewModel>();
window.Show();

Мой MainWindowViewModel разрешается, и вот его конструктор

public MainWindowViewModel(IWorkspaceFactory workspaceFactory, IWindowManager windowManager)
    {
        _workspaceFactory = workspaceFactory;
        _windowManager = windowManager;
        _windowManager.Changed += new EventHandler(DialogChanged);
        ControlPanel = new ListCommandsViewModel();
        foreach (string s in _workspaceFactory.GetWorkspaceList())
        {
            ControlPanel.List.Add(new CommandViewModel(s, new RelayCommand<string>(OpenWorkspace)));
        }
    }

Обратите внимание, что я подписываюсь на событие в WindowManager. Unity должны разрешать WorkspaceFactory и WindowManager, чтобы их экземпляры создавались.

Вот реализация IWorkspaceFactory:

public class WorkspaceFactory : IWorkspaceFactory
{
    private IUnityContainer _container;

    public WorkspaceFactory(IUnityContainer container)
    {
        _container = container;
    }

    public ViewModel.WorkspaceViewModel GetWorkspace(string workspace)
    {
        return _container.Resolve<WorkspaceViewModel>(workspace);
    }

    public ICollection<string> GetWorkspaceList()
    {
        return _container.Registrations.Where(r => r.RegisteredType == typeof(WorkspaceViewModel)).Select(r => r.Name).ToList();
    }

}

Поскольку я зарегистрировал оригинальный контейнер как экземпляр, он должен быть тем, что передается на завод. Поэтому я позволяю тому же контейнеру разрешить рабочую область, которая захватывает IWindowsManager в качестве параметра ctro. Таким образом, он должен получать экземпляр sama, так как MainWindowViewModel получил право?

Но если я инициирую событие изнутри рабочей области, MainView никогда не будет уведомлен, в действительности событие Changed будет пустым, так как это отдельный экземпляр IWindowManager.

Как это может быть?

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

Ответы [ 2 ]

2 голосов
/ 27 февраля 2011

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

2 голосов
/ 27 февраля 2011

Извините, но я думаю, что вы выключены - если Unity похож на AutoFac, то поведение по умолчанию будет "новый экземпляр на запрос".

Это, безусловно, то, как документы выглядят "Это создаст новыйэкземпляр зарегистрированного, сопоставленного или запрошенного типа каждый раз "- см. http://msdn.microsoft.com/en-us/library/cc440953.aspx

. Чтобы исправить это, предоставьте LifetimeManager при регистрации типа - например, ContainerControlledLifetimeManager (см. http://msdn.microsoft.com/en-us/library/cc440953.aspx)

...