Pergunta

Mídia Navegador tem um modelo de provedor, este é basicamente uma cadeia de classes que são chamados em uma ordem específica para cada entidade.

Assim, por exemplo, temos:

        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());

A ordem dos provedores na lista é significativas prestadores de ordem superior têm precedência sobre os mais baixos da ordem.

Recentemente, eu tentei fazer esta parte extensível. Então um terceiro DLL pode definir os seus próprios provedores que vai ser injetados na nossa cadeia.

O problema é que uma vez que permitem a 3 partes para injectar-se na cadeia de você perder um lugar central para definir esta ordem.

Minha solução atual que eu sou um pouco desconfortável com é definir um atributo de prioridade opcional com cada fornecedor e da ordem, em seguida, pela prioridade.

Assim, por exemplo eu tenho agora:

[ProviderPriority(20)]
class ImageByNameProvider{}

Isso permite que 3 partes para definir sua posição na cadeia.

Outra soluções Pensei sobre eram antes e depois atributo Ex.

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

Mas, eu não tenho certeza se isso é mais fácil ou mais difícil para o programa contra.

Existem outras soluções para este problema? Qual a solução que você vai com?

Talvez, eu deveria apenas manter a lista para os provedores de núcleo e adicionar antes / depois attribs para provedores de terceiros ...

Foi útil?

Solução

Parece que há realmente algumas questões diferentes aqui que devem ser abordadas. O problema fundamental é tentar chegar a um mecanismo que permite que um objeto arbitrário para ser inserido no a uma lista existente em algum ponto no meio dessa lista.

Você não descrevem o que a interface IMetadataProvider realmente parece, mas ele deve ter alguma forma para o identificar um provedor (melhor opção seria usar um Guid). A vantagem sobre usando o nome da classe é que ele permite renomear as classes conforme necessário durante a refatoração, etc., sem afetar personalizados provedores (3 ª parte), enquanto você manter o Guid o mesmo.

Ao invés de usar uma lista simples que você provavelmente deve derivar sua própria lista:

class ProviderList : List<IMetadataProvider { }

que expõe um caminho para um provedor personalizado (parte 3) para instalar / desinstalar-se a partir dessa lista. Estes mecanismos precisam ser inteligente o suficiente para saber como inserir o novo provedor no meio da cadeia, mas também inteligente o suficiente para saber como lidar com vários provedores personalizados que foram inseridos. Da mesma forma, as necessidades do processo de remoção para ser inteligente, assim como para lidar com preocupações semelhantes e também garantir que alguém não tentar remover um dos seus fornecedores "core".

Uma abordagem boa aqui seria provavelmente para passar o Guid do provedor que deseja ser inserido depois como um parâmetro para o método de instalação (). O método Remove () seria igualmente tomar o Guid do provedor a ser removido.

Por exemplo, digamos que eu inserir um novo provedor depois MovieProviderFromXml. Em seguida, outro 3rd party também instala um novo provedor depois MovieProviderFromXml. Qual deve ser a nova ordem da cadeia? Será o segundo provedor de sempre inserir imediatamente após MovieProviderFromXml ou o faz começar lá e então pular quaisquer provedores personalizados e inserir após o último provedor personalizado instalado (assim, pouco antes do próximo provedor "core"?

relacionadas a essa pergunta é a idéia de que você precisa ter alguma maneira de distinguir entre seus fornecedores "core" e um provedor personalizado.

Finalmente, você precisa ter certeza de que há uma maneira de falhas punho na cadeia, especialmente quando um provedor personalizado é inserido no local errado.

Você quer sempre manter uma lista de base ( "master") de sua cadeia padrão. Quando um novo provedor está instalado no meio dessa cadeia, uma nova cadeia deve ser criada, mas você não quer perder a cadeia base. Isso lhe dá a capacidade de redefinir a parte de trás da cadeia para o estado padrão.

Encadeamento com base na prioridade é problemática em que você então tem que determinar como tratar colisões prioritários. Tanto quanto um Antes / Depois conjunto de atributos, você permitiria ambos no mesmo provedor? Provavelmente não, para que ele possa fazer mais sentido para criar uma ProviderChainAttribute que tem uma propriedade ChainInsert enum, onde os valores define ChainInsert Antes e depois como enum. Isso permite que você forçar o provedor personalizado para tomar uma decisão quanto a saber se instala antes ou após o provedor de especificado. Eu ainda usaria um Guid em vez do tipo.

Esperemos que este dá-lhe algumas outras ideias sobre como abordar este problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top