簡體   English   中英

在Prism 6中加載所有模塊后,使用ViewModel初始化Shell

[英]Initialize Shell with ViewModel after all modules loaded in Prism 6

我的Shell / MainWindow的ViewModel(通過AutoWireViewModel="True" )請求使用ConfigurationModuleCatalog在啟動時加載到模塊中的依賴項。
因為Shell在模塊之前被初始化,所以DI容器顯然無法解析它,因此應用程序崩潰了。

public class MainWindowViewModel : BindableBase
{
    // Cannot resolve IService
    public MainWindowViewModel(IService service)
    {
    }
}

我已經嘗試過這篇文章的兩種方法,但兩種方法都沒有用。

我這樣試過:

public interface IShellService
{
    int NumberOfLoadedModules { get; }

    void FlagModuleAsLoaded();
}

public class ShellService : IShellService
{
    private readonly IModuleCatalog _moduleCatalog;

    public ShellService(IModuleCatalog moduleCatalog)
    {
        _moduleCatalog = moduleCatalog;
    }

    public int NumberOfLoadedModules { get; private set; }

    public void FlagModuleAsLoaded()
    {
        NumberOfLoadedModules++;

        if (NumberOfLoadedModules != _moduleCatalog.Modules.Count())
            return;

        InitializeShell();
    }

    private static void InitializeShell()
    {
         Application.Current.MainWindow.Show();
    }
}

internal class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return null;
    }

    protected override void InitializeShell()
    {
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        Container.RegisterInstance<IShellService>(new ShellService(ModuleCatalog), new ContainerControlledLifetimeManager());
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ConfigurationModuleCatalog();
    }
}

用法

public abstract class ModuleBase : IModule
{
    private readonly IShellService _shellService;

    protected ModuleBase(IShellService shellService)
    {
        _shellService = shellService;
    }

    public void Initialize()
    {
        InitializeInternal();
        FlagAsLoaded();
    }

    public abstract void InitializeInternal();

    public void FlagAsLoaded()
    {
        _shellService.FlagModuleAsLoaded();
    }
}

public class FooModule : ModuleBase
{
    IUnityContainer _container;

    public MusicUIModule(IUnityContainer container, IShellService shellService) : base(shellService)
    {
        _container = container;
    }

    public override void InitializeInternal()
    {
        _container.RegisterType<IService, Service>();
    }
}

它開始計算模塊,然后由於相同的原因應用程序崩潰。
如果上述方法不符合我的目的,那么該問題怎么解決?

謝謝!

我試圖實現Haukinger的建議並以這種方式做到這一點很好:

// Factory --------------------------------------------------------

public interface IDependencyFactory
{
    IService GetService();
}

public class DependencyFactory : IDependencyFactory
{
    private readonly IUnityContainer _container;

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

    public IService GetService()
    {
        return _container.Resolve<IService>();
    }
}

// PubSubEvent ------------------------------------------------------

public class AllModulesLoaded : PubSubEvent
{
}

// Bootstrapper -----------------------------------------------------

internal class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow.Show();
    }

    protected override void InitializeModules()
    {
        base.InitializeModules();

        // Publishing event to tell subscribers that the modules are loaded
        var eventAggregator = Container.Resolve<IEventAggregator>();
        eventAggregator?.GetEvent<AllModulesLoaded>().Publish();
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();

        // ...
        Container.RegisterType<IDependencyFactory, DependencyFactory>();
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ConfigurationModuleCatalog();
    }
}

// ViewModel ---------------------------------------------------------

public class MainWindowViewModel : BindableBase
{
    private IService _service;
    private readonly IEventAggregator _eventAggregator;
    private readonly IDependencyFactory _dependencyFactory;

    public MainWindowViewModel(IEventAggregator eventAggregator, IDependencyFactory dependencyFactory)
    {
        _eventAggregator = eventAggregator;
        _dependencyFactory = dependencyFactory;

        _eventAggregator.GetEvent<AllModulesLoaded>().Subscribe(OnAllModulesLoaded);
    }

    private void OnAllModulesLoaded()
    {
        var service = _dependencyFactory.GetService();
        if (service != null)
            _service = service ;

        _eventAggregator.GetEvent<AllModulesLoaded>().Unsubscribe(OnAllModulesLoaded);
    }
}

我將shell隱藏在工廠/提供程序后面,然后在加載最后一個模塊時創建/獲取它。 shell的視圖模型訂閱了一個AllModulesLoaded事件,當base.InitializeModules返回時,它會從引導程序的InitializeModules觸發,以通知依賴項可用。 或者工廠/提供者訂閱該事件,並且shell會輪詢它,具體取決於您希望如何使用依賴項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM