如何在 Prism 应用程序的各个模块中从 Unity 容器获取相同的对象实例

本文关键字:获取 Unity 实例 对象 Prism 应用程序 模块 | 更新日期: 2023-09-27 18:30:53

我有一个 Prism 应用程序,其中有三个模块:

    共享服务模块
  • (我正在使用共享服务在模块之间进行通信)
  • 模块A
  • 模块B

共享服务模块只有接口及其实现CommonService:

public interface ICommonService
{
    string SomeStorage { get; set; }        
}
public class CommonService : ICommonService
{
    string fooStorage;
    public string FooStorage
    {
        get
        {
           return fooStorage;
        }
        set
        {
            fooStorage = value;
            OnPropertyChanged("FooStorage");                                
        }
    }
}

我想要的是使用共享服务在模块之间创建通信。所以我在模块AViewModelA上分配«ModuleAValue»,然后我想在模块BViewModelB中读取这个值。让我们看看细节。

我在模块 AViewModelA 中创建单个ICommonService实例,并将值"ModuleAValue"分配给FooStorage

查看模型A的方法:

unityContainer = new UnityContainer();
unityContainer.RegisterType<ICommonService, CommonService>(new ContainerControlledLifetimeManager());
IMyService someFoo = unityContainer.Resolve<ICommonService>();
someFoo.FooStorage = "ModuleAValue";//value is "ModuleAValue" in FooStorage

然后我想在模块 B 的视图模型 B 中读取这些数据。但是FooStorage的值不是"模块 A",而只是空值:

视图模型B的方法:

IUnityContainer unityContainer=new UnityContainer//creation of UnityContainer in ModuleB
ICommonService someFoo = unityContainer.Resolve<CommonService>();
string str=someFoo.FooStorage;//value is empty in 
FooStorage, but it should be "ModuleAValue"    

我的引导程序是:

public class Bootstrapper:UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<Shell>();
    }
    protected override void InitializeShell()
    {
        base.InitializeShell();
        App.Current.MainWindow = (Window)Shell;
        App.Current.MainWindow.Show();
    }
    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        Container.RegisterType<IShellViewModel, ShellViewModel>();
        RegisterTypeIfMissing(typeof(IMyService), typeof(MyService), true);
    }
    protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
    {
        RegionAdapterMappings mappings = base.ConfigureRegionAdapterMappings();
        mappings.RegisterMapping(typeof(StackPanel), Container.Resolve<StackPanelRegionAdapter>());
        return mappings;
    }
    protected override IModuleCatalog CreateModuleCatalog()
    {
        ModuleCatalog catalog = new ModuleCatalog();
        catalog.AddModule(typeof(ModuleAModule));
        catalog.AddModule(typeof(ModuleBModule));
        return catalog;
    }
}

我做错了什么?在我看来,Unity 总是创建新的CommonService实例。从 Unity 容器获取相同的实例时我做错了什么?

任何帮助将不胜感激!

如何在 Prism 应用程序的各个模块中从 Unity 容器获取相同的对象实例

应用的

引导程序会为你创建一个UnityContainer,请参阅UnityBootstrapper.cs

protected virtual IUnityContainer CreateContainer()
{
    return new UnityContainer();
}

引导程序还应将容器注册为 viewmodel 工厂:

protected override void ConfigureContainer()
{
    base.ConfigureContainer();
    ViewModelLocationProvider.SetDefaultViewModelFactory( type => Container.Resolve( type ) );
}

在模块定义类中,可以将此"全局"容器作为依赖项注入:

public class ClientModule : IModule
{
    private readonly IUnityContainer _unityContainer;
    public ClientModule( IUnityContainer unityContainer )
    {
        _unityContainer = unityContainer;
    }
}

在模块的初始化中,向以下容器注册类型或实例:

public void Initialize()
{
    // Register services
    _unityContainer.RegisterType<IGameClock, LocalGameClock>( new ContainerControlledLifetimeManager() );
    _unityContainer.RegisterType<IWorldStateService, LocalWorldStateService>( new ContainerControlledLifetimeManager() );
}

在视图(在 xaml 中)中,现在可以使用 ViewModelLocator.AutoWireViewModel="True" 自动为视图创建视图模型。ViewModelLocationProvider将使用"全局"容器来解析视图模型(如上所述),因此所有视图模型都将收到我们的相同实例,例如IGameClock

辅助建议:你不想自己直接打电话给Resolve。以这种方式使用它首先违背了使用统一性的全部目的。最好将依赖项作为构造函数参数注入,并且仅在最高级别(即在模块初始化中)使用容器。而且你永远不需要创建多个容器,以免你确切地知道你在做什么。

不应创建新的容器实例。通常,应用程序中应该只有一个容器实例。如果您使用的是棱镜,则视图模型也应该从容器创建(如果棱镜负责视图模型的创建,而不是从容器创建)。在这种情况下,只需使用ICommonService类型的参数在视图模型中创建构造函数,如下所示:

public ViewModelA(ICommonService service) { ... }

然后在创建视图模型期间,服务的相同实例将被注入到该视图模型。

通常,公共服务在应用程序启动期间在命令行管理程序中注册。但是,如果需要,也可以在模块中注册服务,只需使用在应用程序启动期间创建的相同unity容器即可。在视图模型中,使用带有 IUnityContainer 类型的参数的构造函数。