如何使用MEF导出和导入应用程序服务?

5

我现在正在使用MEF,但是我想要的答案可能与MEF无关--它都是依赖注入--我只是在这里举例使用MEF术语。

简短的背景故事,我在MSDN上阅读了这篇文章,重点是组合应用

在这个图中有三件事情,壳、应用程序服务和模块。所以这就是一个组合应用程序。

alt text
(来源:microsoft.com)

我不完全明白应用程序服务部分。什么是服务,它是什么样子的?你如何通过一个模块来公开一个服务,如何从不同的模块中使用一个服务?

我真的很想看到一些漂亮的小代码示例,没有花哨的东西,但是可以说明所有这些是如何实现的(应用程序服务部分)。


是的,那张图片中的颜色选择太糟糕了... - John Leidegren
2个回答

3

就MEF而言,应用程序服务只是另一个可组合的部分。您可以组合任何接口或类来充当服务。

每个服务都将有一些您想要实现的接口或基类。您可以通过某种类型的IService接口(并使用[ImportMany]导入所有服务)批量执行这些操作,但通常,您会需要不同的服务类型。

然后,根据需要将其导入到您的类中。例如,假设您有一个用于服务的公共接口库,并提供:

public interface IDataRepostory
{
     public IList<MyType> MyTypes { get; }
}

您可以创建一个单独的库,用于导出特定类型:

[Export(typeof(IDataRepository))]
public class Repository: IDataRepostory
{
    // implement interface for this specific "service"
}

您的主程序将能够根据需要导入此内容,并针对其编写代码。例如,假设您想显示客户信息,则需要从数据层加载客户信息。如果您想通过存储库进行加载,您可以将存储库导入到应用程序的特定部分:

public class CustomersViewModel
{
     [Import]
     public IDataRepository
     {
         get; set;
     }

     // ...
}

然后,您可以将此服务直接编写到您的应用程序中。

这被视为“应用程序服务”,因为它是某些通用服务的应用程序特定实现 - 它不是与视图相关的组件,并且可以在整个应用程序中使用。


如果有多个应用程序服务满足导入要求,您将如何区分它们?使用元数据吗?还是有更好的方法?或者这样做是错误的。我知道MEF在发生这种情况时会抛出异常,所以我真的只想要一个接口和一个具体实现吗? - John Leidegren
@John:你必须使用[ImportMany],然后查询服务或使用元数据来确定要使用哪个。否则,你会得到一个异常。 - Reed Copsey
那么,复合应用程序中的所有内容都是应用程序服务吗? - John Leidegren
这一切都非常简洁…然而,一开始很难理解…感谢你为我澄清了一些问题。虽然我现在还不知道它是什么,但这肯定会有所帮助,但不能免费解决我的问题。是否有什么特别需要注意的事项,并且应该避免以保持良好的设计? - John Leidegren
最重要的是确保非常清楚地知道从哪里以及如何拉取“部件”,以及它们被组合在哪里。如果您正在进行WPF或Silverlight,则CompositionInitializer非常方便...(请参见:http://reedcopsey.com/2010/03/26/mef-compositioninitializer-for-wpf/) - Reed Copsey
显示剩余4条评论

0
声明服务的接口和实现该接口的导出类。例如,您可能有一个在共享程序集中声明的 IPersonBuilder。您的主模块有实现该接口并导出的 MyPersonBuilder。所有视图都使用导入IPersonBuilder来调用其上的方法,并且使用MEF组合,它们将能够从您的主模块调用MyPersonBuilder上的CreatePerson()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接