【问题标题】:Best way to annotate provider chains注释提供者链的最佳方法
【发布时间】:2010-10-17 22:38:19
【问题描述】:

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

所以例如我们有:

        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 方定义他们在链中的位置。

我想到的另一个解决方案是属性Eg之前和之后。

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

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

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

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

【问题讨论】:

    标签: c# .net provider


    【解决方案1】:

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

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

    与其使用一个简单的列表,不如你应该派生出自己的列表:

    class ProviderList : List<IMetadataProvider { }
    

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

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

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

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

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

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

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

    希望这会给您一些关于如何解决此问题的其他想法。

    【讨论】:

    • Scott,感谢您的宝贵时间和周到的回复,我将在接下来的一天左右尝试扩展我的问题以涵盖您的一些想法,这是一个相当复杂的问题。 +1
    猜你喜欢
    • 2020-09-22
    • 2015-08-18
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多