【问题标题】:Prism+MEF: delayed a service export from prism-modulePrism+MEF:延迟从 prism-module 导出服务
【发布时间】:2010-09-09 19:05:03
【问题描述】:

我有一个基于 Prism (v4 ctp) 和 MEF 的应用程序。 该应用程序具有服务 IService1。我希望这个服务实现是由某个模块导出的(不仅仅是由 MEF 发现的)

public interface IService1 {}
public class Service1Impl: IService1 {}

Service1Impl 没有 ExportAttribute。这是因为我想在我的 Prism 模块中手动创建实现:

[ModuleExport(typeof(SomeModule))]
[PartCreationPolicy(CreationPolicy.Shared)]
public SomeModule: IModule
{
    [Export]
    public IService1 Service1 {get; private set}

    public void Initialize()
    {
        Service1 = new Service1Impl();
    }
}

在其他一些组件中,我想通过 MEF Import 获得 IService1 的实现。 问题是如何在 Prism 调用 Initialize 后告诉 MEF 进行导出(在 SomeModule 中)?

如果我在模块的构造函数中创建服务的实现,那么一切正常,但它与 Prism 的模块初始化过程不一致。 问题是 Prism 在 MEF 的组合完成后初始化模块。 此外,在创建服务实现之前,我需要执行一些复杂的初始化逻辑,并且我不希望它在构造函数中。

那么,我有哪些选择?

【问题讨论】:

    标签: prism mef


    【解决方案1】:

    您尝试过 ModuleDependency 吗?我需要对 MEF 做更多研究,但在 Prism 中,您可以通过 ModuleDependency 保证一个模块的 Initialize 在其他模块之前触发。

    例如,如果您有 SomeOtherModule 在 Initialize 期间需要 IService1,您可以确保 SomeModule 首先以这种方式初始化。

    [ModuleDependency("SomeModule")]
    public class SomeOtherModule : IModule
    {
        [Import]
        public IService1 Service1 {get; set;}
    
        public void Initialize()
        {
            //This ought to be populated now.
            Service1.DoSomething();
        }
    }
    

    我完全有资格说我可能不知道 MEF 的某些内部工作不允许这样做,但这是 Prism 的一般工作方式。

    顺便说一句,当我看到依赖关系时,无论是显式的还是隐式的,我都会问自己:

    1. 服务会被多个模块使用吗?那么,将服务推广为在 Bootstrapper 中构建并由托管应用程序而不是其他模块提供的东西是否有意义?
    2. 如果不是#1,如果模块之间存在依赖关系,这些模块在逻辑上是否相同?他们应该合并吗?如果一个人不能没有另一个人,那么没有理由不将它们结合起来。

    无论如何,最后一个只是需要考虑的事情。

    希望这会有所帮助。

    【讨论】:

    • 谢谢,但老实说,我不喜欢这种方法,因为它会在导出服务的模块和导入服务的模块之间创建依赖关系。我相信这不好。
    • @Shrike 你已经有了隐式依赖。您期望服务实现由另一个模块提供,如果不存在,您的流程的某些部分将失败。这就是为什么我发布了“作为旁白”部分……您的模块之间存在需要解决的依赖关系。我也不喜欢 ModuleDependency,但是您必须以某种方式解决隐含的依赖关系。如果不是 ModuleDependency,那么我列出的其他方法之一。
    【解决方案2】:

    我对 MEF 的使用有点生疏,但这些想法可能有用。如果您的属性是 concreate 实现类型,但您通过指定接口的合同导出属性怎么办(我认为它类似于以下内容):

    [Export(IService1)]
    public Service1Impl Service1 {get; private set}
    

    然后每个对 IService1 接口进行导入检查的模块都将从该模块获取具体实现(这是针对接口进行编码的主要目标)。

    我希望这会引导您朝着正确的方向前进。

    谢谢, 达米安

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2011-07-29
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多