IoC Container Unity 搞乱了我

发布于 2024-10-19 14:37:20 字数 2298 浏览 7 评论 0原文

我可能不明白它应该如何工作。

在我启动应用程序的地方,我这样做:

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 中的一个事件。 WorkspaceFactory 和 WindowManager 应在此处由 Unity 解析,以便创建它们的实例。

这是 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 参数的工作区。那么它应该像 MainWindowViewModel 一样获取 sama 实例吗?

但是,如果我从工作区内部触发事件,MainView 永远不会收到通知,实际上 Changed 事件是空的,就像这是 IWindowManager 的单独实例一样。

怎么可能呢?

我完全不同意吗,我的印象是,如果你不为容器中的类型定义生命周期,你总是会得到相同的实例。

There is a possibility I'm not understanding how it's supposed to work.

Where I start my app I do this:

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();

My MainWindowViewModel gets resolved and here is it's constructor

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)));
        }
    }

Notice that I subscribe to a event in the windowManager. WorkspaceFactory and WindowManager should are resolved here by Unity so instances of them are created.

Here is a implmentation of 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();
    }

}

As I registered the original container as a instance it should be what is passed into the factory. So I'm letting the same Container resolve the workspace that grabs IWindowsManager as a ctro parameter. So it should be getting the sama instance as the MainWindowViewModel got right?

But if I fire off the event from inside the workspace the MainView never gets notified, in actuality the Changed event is empty like this is a seperate instance of IWindowManager.

How may that be?

Am I totally off, I was under the impression that if you don't define a LifeTime for types in containers you alwasy get the same instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

停顿的约定 2024-10-26 14:37:20

抱歉,但我认为你已经关闭了 - 如果 Unity 就像 AutoFac 那么默认行为将是“每个请求新实例”。

这肯定是文档的样子“它将每次创建注册、映射或请求类型的新实例” - 请参阅 http://msdn.microsoft.com/en-us/library/cc440953.aspx

要纠正此问题,请在注册类型时提供 LifetimeManager - 例如 ContainerControlledLifetimeManager(请参阅http://msdn.microsoft.com/en-us/library/cc440953.aspx )

Sorry, but I think you are off - if Unity is like AutoFac then the default behaviour will be "new instance per request".

This is certainly what the docs look like "It will create a new instance of the registered, mapped, or requested type each time" - see http://msdn.microsoft.com/en-us/library/cc440953.aspx

To correct this, provide a LifetimeManager when you Register the type - e.g. ContainerControlledLifetimeManager (see http://msdn.microsoft.com/en-us/library/cc440953.aspx)

萌逼全场 2024-10-26 14:37:20

默认情况下,Unity 将为注册类型解析一个新实例,因此您需要使用不同的范围注册 WorkspaceViewModel。此外,注入容器而不是真正的依赖项也是一个坏主意,因为这会让客户端很难知道它们是什么。

By default, Unity will resolve a new instance for registered types, so you need to register WorkspaceViewModel with a different scope. In addition, it's a bad idea to inject the container instead of the real dependencies since it makes it difficult for the client to know what those are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文