原文:http://msdn.microsoft.com/zh-cn/library/dd460648.aspx
假设您是一个必须提供扩展性支持的大型应用程序的架构师。 您的应用程序必须包含大量可能需要的较小组件,并负责创建和运行这些组件。
解决这一问题的最简单的方法是:将这些组件作为源代码包括在您的应用程序中,然后通过代码直接调用它们。这种做法存在很多明显的缺陷。最重要的是,您无法在不修改源代码的情况下添加新组件,这一限制在 Web 应用程序(举例来说)中也许能够接受,但在客户端应用程序中行不通。同样存在问题的还有,您可能没有对组件的源代码的访问权,因为这些组件可能是由第三方开发的,而出于相同的原因,您也不允许第三方访问您的代码。
一种稍微复杂的方法是:提供扩展点或接口,以允许应用程序与其组件相分离。依据此模型,您可能会提供一个组件能够实现的接口,并提供一个 API 以使该接口能够与您的应用程序进行交互。这一方法可解决需要源代码访问权的问题,但仍具有自己的难点。
由于应用程序缺乏自己发现组件的能力,因此仍必须明确告知应用程序哪些组件可用并应加载。这通常是通过在一个配置文件中显式注册可用组件来实现的。 这意味着,确保组件正确无误成为了一个日常维护问题,尤其是在执行更新操作的是最终用户而非开发人员的情况下。
此外,各组件之间无法进行通信,除非是通过应用程序自身的严格定义的通道。如果应用程序架构师未预计到需要某项通信,则通常是无法进行相应的通信的。
最后,组件开发人员不得不硬依赖于包含他们实现的接口的程序集。这样就很难在多个应用程序中使用同一个组件,另外,在为组件创建测试框架时也会造成问题。
有别于这种显式注册可用组件的做法,MEF 提供一种通过“组合”隐式发现组件的方法。MEF 组件(称为“部件”)以声明方式同时指定其依赖项(称为“导入”)及其提供的功能(称为“导出”)。 创建一个部件时,MEF 组合引擎会使其导入与其他部件提供的内容相符合。
此方法解决了上一节中讨论的问题。由于 MEF 部件以声明方式指定其功能,因此在运行时可发现这些部件。这意味着,应用程序无需硬编码的引用或脆弱的配置文件即可利用相关部件。通过 MEF,应用程序可以通过部件的元数据来发现并检查部件,而不用实例化部件,或者甚至不用加载部件的程序集。 因此,没有必要仔细指定应何时以及如何加载扩展。
除了部件提供的导出以外,部件还可以指定其导入,然后由其他部件填充这些导入。这不仅使各部件之间的通信变为可能,而且使通信变得很容易,此外,还可以合理地分解代码。 例如,可以将许多组件的公用服务分解到单独的部件中,以便于修改或替换。
由于 MEF 模型不要求硬依赖于特定的应用程序程序集,因此,此模型允许在应用程序之间重用扩展。利用此模型,还可以轻松地开发独立于应用程序的测试工具来测试扩展组件。
使用 MEF 编写的可扩展应用程序会声明一个可由扩展组件填充的导入,而且还可能会声明导出,以便向扩展公开应用程序服务。每个扩展组件都会声明一个导出,而且还可能会声明导入。通过这种方式,扩展组件本身是自动可扩展的。
假设您是一个必须提供扩展性支持的大型应用程序的架构师。 您的应用程序必须包含大量可能需要的较小组件,并负责创建和运行这些组件。
解决这一问题的最简单的方法是:将这些组件作为源代码包括在您的应用程序中,然后通过代码直接调用它们。这种做法存在很多明显的缺陷。最重要的是,您无法在不修改源代码的情况下添加新组件,这一限制在 Web 应用程序(举例来说)中也许能够接受,但在客户端应用程序中行不通。同样存在问题的还有,您可能没有对组件的源代码的访问权,因为这些组件可能是由第三方开发的,而出于相同的原因,您也不允许第三方访问您的代码。
一种稍微复杂的方法是:提供扩展点或接口,以允许应用程序与其组件相分离。依据此模型,您可能会提供一个组件能够实现的接口,并提供一个 API 以使该接口能够与您的应用程序进行交互。这一方法可解决需要源代码访问权的问题,但仍具有自己的难点。
由于应用程序缺乏自己发现组件的能力,因此仍必须明确告知应用程序哪些组件可用并应加载。这通常是通过在一个配置文件中显式注册可用组件来实现的。 这意味着,确保组件正确无误成为了一个日常维护问题,尤其是在执行更新操作的是最终用户而非开发人员的情况下。
此外,各组件之间无法进行通信,除非是通过应用程序自身的严格定义的通道。如果应用程序架构师未预计到需要某项通信,则通常是无法进行相应的通信的。
最后,组件开发人员不得不硬依赖于包含他们实现的接口的程序集。这样就很难在多个应用程序中使用同一个组件,另外,在为组件创建测试框架时也会造成问题。
有别于这种显式注册可用组件的做法,MEF 提供一种通过“组合”隐式发现组件的方法。MEF 组件(称为“部件”)以声明方式同时指定其依赖项(称为“导入”)及其提供的功能(称为“导出”)。 创建一个部件时,MEF 组合引擎会使其导入与其他部件提供的内容相符合。
此方法解决了上一节中讨论的问题。由于 MEF 部件以声明方式指定其功能,因此在运行时可发现这些部件。这意味着,应用程序无需硬编码的引用或脆弱的配置文件即可利用相关部件。通过 MEF,应用程序可以通过部件的元数据来发现并检查部件,而不用实例化部件,或者甚至不用加载部件的程序集。 因此,没有必要仔细指定应何时以及如何加载扩展。
除了部件提供的导出以外,部件还可以指定其导入,然后由其他部件填充这些导入。这不仅使各部件之间的通信变为可能,而且使通信变得很容易,此外,还可以合理地分解代码。 例如,可以将许多组件的公用服务分解到单独的部件中,以便于修改或替换。
由于 MEF 模型不要求硬依赖于特定的应用程序程序集,因此,此模型允许在应用程序之间重用扩展。利用此模型,还可以轻松地开发独立于应用程序的测试工具来测试扩展组件。
使用 MEF 编写的可扩展应用程序会声明一个可由扩展组件填充的导入,而且还可能会声明导出,以便向扩展公开应用程序服务。每个扩展组件都会声明一个导出,而且还可能会声明导入。通过这种方式,扩展组件本身是自动可扩展的。