0

媒体浏览器有一个提供者模型,这基本上是一个类链,每个实体按特定顺序调用。

例如,我们有:

        providers = new List<IMetadataProvider>();
        providers.Add(new ImageFromMediaLocationProvider());
        providers.Add(new ImageByNameProvider());
        providers.Add(new MovieProviderFromXml());
        providers.Add(new MovieDbProvider());
        providers.Add(new TVProviderFromXmlFiles());
        providers.Add(new TvDbProvider());
        providers.Add(new VirtualFolderProvider());
        providers.Add(new FrameGrabProvider());
        providers.Add(new MediaInfoProvider());

列表中提供程序的顺序是显着的,较高顺序的提供程序优先于较低顺序的提供程序。

最近,我试图使这部分可扩展。因此,第三方 DLL 可以定义自己的提供程序,这些提供程序将被注入我们的链中。

问题是,一旦您允许第 3 方将自己注入链中,您就失去了定义此顺序的中心位置。

我目前有点不舒服的解决方案是为每个提供者定义一个可选的优先级属性,然后按优先级排序。

例如,我现在有:

[ProviderPriority(20)]
class ImageByNameProvider{}

这允许第 3 方定义他们在链中的位置。

我想到的另一个解决方案是在属性之前和之后,例如。

[Before(typeof(ImageByNameProvider))]
class ImageFromMediaLocationProvider {} 

但是,我不确定这是否更容易或更难编程。

这个问题还有其他解决方案吗?你会选择哪种解决方案?

也许,我应该只保留核心提供商的列表并为第三方提供商添加之前/之后的属性......

4

1 回答 1

1

似乎这里实际上应该解决一些不同的问题。基本问题是试图提出一种机制,允许将任意对象插入到现有列表中的某个位置。

您没有描述 IMetadataProvider 接口的实际外观,但它应该有某种方式来唯一标识提供程序(最好的选择是使用 Guid)。使用类名的好处是它允许您在重构等期间根据需要重命名类,而不会影响自定义(第 3 方)提供程序,只要您保持 Guid 相同。

而不是使用一个简单的列表,您可能应该派生自己的列表:

class ProviderList : List<IMetadataProvider { }

这为自定义(第 3 方)提供商提供了一种从该列表安装/卸载自身的方式。这些机制需要足够聪明,知道如何将新提供者插入到链的中间,但也需要足够聪明,知道如何处理已插入的多个自定义提供者。同样,删除过程也需要聪明,以处理类似的问题,并确保有人不会试图删除您的“核心”提供商之一。

这里的一个好方法可能是将要插入的提供程序的 Guid 作为参数传递给 Install() 方法。Remove() 方法同样会采用要删除的提供者的 Guid。

例如,假设我在 MovieProviderFromXml 之后插入了一个新的提供程序。然后另一个第 3 方也在 MovieProviderFromXml 之后安装了一个新的提供程序。新的链序应该是什么?第二个提供程序总是在 MovieProviderFromXml 之后立即插入,还是从那里开始然后跳过任何自定义提供程序并在安装最后一个自定义提供程序之后插入(所以就在下一个“核心”提供程序之前?

与该问题相关的是您需要有某种方法来区分“核心”提供者和自定义提供者的想法。

最后,您需要确保有一种方法可以处理链中的故障,尤其是当自定义提供程序插入错误的位置时。

您确实希望始终维护默认链的基本(“主”)列表。当在该链的中间安装一个新的提供者时,应该创建一个新的链,但您不想松开基本链。这使您能够将链重置为默认状态。

基于优先级的链接是有问题的,因为您必须确定如何处理优先级冲突。至于 Before/After 属性集,您是否允许在同一个提供者上使用两者?可能不是,因此创建一个具有 ChainInsert 枚举属性的 ProviderChainAttribute 可能更有意义,其中 ChainInsert 将 Before 和 After 定义为枚举值。这允许您强制自定义提供程序决定它是在指定提供程序之前还是之后安装。我仍然会使用 Guid 而不是类型。

希望这能给你一些关于如何解决这个问题的其他想法。

于 2009-04-07T02:07:34.323 回答