【问题标题】:How to inject new instance at run time in Prism?如何在运行时在 Prism 中注入新实例?
【发布时间】:2019-09-20 02:02:07
【问题描述】:

我将 Prism 7.1 用于 WPF 应用程序。 我尝试使用内置的 IOC(Unity),但我不知道如何在运行时从方法或 containerProvider 解析新实例。但似乎 IContainerProvider 无法注入到我的视图模型中。我有什么选择吗?

我想这样做以重新加载我的数据库上下文。有人告诉我,创建新的上下文是最简单的。

    public class ProjectViewModel : BindableBase
    {
        private UnitOfWork unitOfWork;
        private IContainerProvider containerProvider;
        private IEventAggregator eventAggregator;
        #region Constructor
        public ProjectViewModel(UnitOfWork unitOfWork, IContainerProvider cp, IEventAggregator ea)
        {
            this.unitOfWork = unitOfWork;
            containerProvider = cp;
            eventAggregator = ea;
            eventAggregator.GetEvent<SendReloadDataEvents>().Subscribe(Reload);
            Reload();
        }
        #endregion

        private void Reload()
        {
            this.unitOfWork = containerProvider.Resolve<UnitOfWork>();
            Projects = new ObservableCollection<Projects>(unitOfWork.ProjectRepo.GetAll());
            Customers = new ObservableCollection<Customers>(unitOfWork.CustomerRepo.Find(x => x.Projects.Count > 0));
            SelectedProjectType = null;
        }
//Other logic continues
}

【问题讨论】:

    标签: wpf unity-container prism


    【解决方案1】:

    注入容器是一种反模式,因此我们会尽量避免这种情况并改为注入工厂。事实上,IContainerProviderIContainerRegistry 并没有为此注册自己,因此无法注入。

    虽然工厂很简单:

    public class ProjectViewModel : BindableBase
    {
        private UnitOfWork unitOfWork;
        private Func<UnitOfWork> unitOfWorkFactory;
        private IEventAggregator eventAggregator;
        #region Constructor
        public ProjectViewModel(Func<UnitOfWork> unitOfWorkFactory, IEventAggregator ea) // no need to inject a unit of work
        {
            _unitOfWorkFactory = unitOfWorkFactory;
            eventAggregator = ea;
            ea.GetEvent<SendReloadDataEvents>().Subscribe(Reload); // prefer the parameter
            Reload();
        }
        #endregion
    
        private void Reload()
        {
            this.unitOfWork = _unitOfWorkFactory(); // create a new one here (the container does the work but is hidden)
            Projects = new ObservableCollection<Projects>(unitOfWork.ProjectRepo.GetAll()); // I'd rather update the existing collection
            Customers = new ObservableCollection<Customers>(unitOfWork.CustomerRepo.Find(x => x.Projects.Count > 0)); // same here, or probably, it could just be IEnumerable
            SelectedProjectType = null;
        }
    //Other logic continues
    }
    

    请注意,这个Func&lt;&gt; 工厂仅适用于最简单的情况。如果您需要将参数传递到产品构造函数中,则必须按照in this answer 的描述自行编写代码。还要注意容器是如何从不出现在任何地方的(除了它被配置的地方),让你的代码依赖于容器是不必要的,并且会使测试变得更丑陋。

    【讨论】:

    • 感谢您的回答。我对 Func 工厂不熟悉。如何在 Prism 容器中注册 Func 工厂?通常我们使用方法“containerRegistry.Register();”。我不认为我可以用 Func 代替 class...
    • Unity 自动创建Func&lt;&gt;。只需注册您的类型并注入Func,您就会得到一个延迟的Resolve,当然也可以与接口一起使用,即containerRegistry.Register&lt;ISomething,TheImplementation&gt;(); -> public Consumer( Func&lt;ISomething&gt; injectedFactory)
    • 好的。这很棒。现在我知道它是如何工作的了。非常感谢,豪金格。祝你有美好的一天。
    猜你喜欢
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2015-04-06
    • 2016-07-06
    相关资源
    最近更新 更多