injeção de dependência de tipo genérico: Como injectar T

votos
4

Eu quero lidar com diferentes tipos de documentos da mesma maneira no meu aplicativo Portanto: Eu tenho uma interface genérica assim.

public interface IDocHandler<T>where T: class
{

T Document { get;set;}

void Load(T doc);

void Load(string PathToDoc);

void Execute();

void Execute(T doc);

}

E para diferentes tipos de documentos que implementar essa interface.

por exemplo:

public class FinanceDocumentProcessor:IDocumentHandler<ReportDocument>
{} 


public class MarketingDocumentProcessor:IDocumentHandler<MediaDocument>
{} 

Então eu posso fazer, claro, algo como isto:

IDocumentHandler<ReportDocument> docProc= new FinanceDocumentProcessor();

Seria interessting saber como eu poderia injetar T em tempo de execução para fazer a linha acima loosly juntamente ...

IDocumentHandler<ReportDocument> docProc = container.resolve(FinanceDocumentProcessor());

mas eu quero decidir por Configuração wether eu quero ter o meu FinanceDomcumentProcessor ou o meu MarketingDocumentProcessor ... portanto eu teria que injetar T no site esquerdo, também ... Desde que eu tenho que usar c # 2.0 Eu não posso usar a palavra mágica var, que ajudaria muito neste caso ... mas como eu posso projetar este seja aberto e flexível ...


Desculpe pelo mal-entendido e obrigado por todos os comentários, mas eu tenho um outro exemplo para o meu desafio (talvez eu estou usando o projeto errado para isso) ... Mas eu dou-lhe uma tentativa: Mesma situação, mas explicação diferente

Exemplo de imagem que tenho:

ReportingService, Crystal, ListAndLabel Três tipos diferentes de relato de documentos. Eu tenho um manipulador genérico IReportHandler<T>(seria o mesmo que acima), este Handler fornece todas as funcionalidades para o tratamento de um documento de relatório. por exemplo

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

Agora eu quero usar um framework como o Unity (ou algum quadro mais) para injeção de dependência para decidir através de configuração se eu quero usar o Crystal, Reportingservicesou Lista e Label.

Quando eu especificar o meu mapeamento I pode injetar o meu ChrystalReportHandler, mas como posso injetar T no lado esquerdo ou no melhor palavra o tipo de ReportDocument.

IReportHandler<T (this needs also to be injected)> = IOContainer.Resolve(MyMappedType here) 

Meu problema é o local do curso deixou porque ele é acoplado ao tipo, mas eu tenho o meu mapeamento ... seria possível gerar um objeto com base em Mapeamento e atribuir o tipo mapeado? ou basicamente injetar T no lado esquerdo, também? Ou é esta abordagem não é adequado para esta situação.

Publicado 10/12/2008 em 10:05
fonte usuário
Em outras línguas...                            


3 respostas

votos
2

Penso que com o seu design atual, você está criando uma "dependência" entre IDocumentHandlere um documento específico ( ReportDocumentou MediaDocument) e por isso, se você quiser usar IDocumentHandler<ReportDocument or MediaDocument>diretamente no seu código, você deve assumir que o recipiente vai lhe dar apenas isso. O recipiente não deve ser responsável por resolver o tipo de documento neste caso.

Você consideraria mudar seu projeto como este?

public interface IDocumentHandler
{
    IDocument Document { get; set; }

    void Load(IDocument doc);

    void Load(string PathToDoc);

    void Execute();

    void Execute(IDocument doc);

}

public class IDocument { }
public class ReportDocument : IDocument { }
public class MediaDocument : IDocument { }
public class FinanceDocumentProcessor : IDocumentHandler { }
public class MarketingDocumentProcessor : IDocumentHandler { }
Respondeu 10/12/2008 em 11:20
fonte usuário

votos
1

Se eu entendi corretamente, você tem duas opções.

  1. se você tem IDocHandler interface e múltiplas classes que implementam isso, você tem que registrar cada tipo explicitamente, como este:

    container.AddComponent> (typeof (FooHandler));

  2. se você tiver um DocHandler classe pode registar-se com o componente usando tipo genérico aberto

    container.AddComponent (typeof (IDocHandler <>), typeof (DocHandler <>));

em seguida, cada vez que você resolver IDocHandler você vai ter uma instância de DocHandler e quando você resolver IDocHandler você terá DocHandler

espero que ajude

Respondeu 22/12/2008 em 23:27
fonte usuário

votos
1

Você precisa usar uma interface não-genéricos no lado esquerdo.

Experimentar:

public interface IDocumentHandler { }
public interface IDocumentHandler<T> : IDocumentHandler { }

Isto irá criar duas interfaces. Coloque tudo T-específica não-comum, na interface de base, e tudo o mais no genérico.

Desde que o código que você deseja resolver um objeto em que você não sabe o tipo de processador para, você não pode chamar qualquer um o código T-específica lá de qualquer maneira, para que você não perder nada usando o não Interface -generic.


Editar : Eu observo a minha resposta foi downvoted. Seria bom se as pessoas downvoting as coisas iriam deixar um comentário por que eles fizeram isso. Eu não me importo sobre o ponto de reputação, que é apenas menor ruído, neste ponto, mas se há algo seriamente errado com a resposta, então eu gostaria de saber para que eu possa excluir a resposta (se é maneira fora do alvo ) ou corrigi-lo.

Agora, neste caso eu suspeito que ou o questionee original tem downvoted-lo e, assim, ou não colocaram informação suficiente, de modo que ele está realmente perguntando sobre algo diferente do que ele perguntou sobre, ou ele não entendia muito bem a minha resposta, que é compreensível, uma vez que foi um pouco curto, ou que alguém que não entendia downvoted que, mais uma vez, pelo mesmo motivo.

Agora, para elaborar.

Você não pode injetar nada "no lado esquerdo". Isso não é possível. Esse código tem que compilar, ser correto, e ser 100% "lá" em tempo de compilação. Você não pode dizer "vamos dizer-lhe o que T é em tempo de execução" para essa parte. Simplesmente não é possível.

Assim, a única coisa que você está com a esquerda é para remover o T completamente. Tornar o código que utiliza a dependência não depender de T, em tudo. Ou, pelo menos, usar o reflexo para descobrir o que T é e fazer as coisas com base nesse conhecimento.

Isso é tudo o que você pode fazer. Você não pode fazer o código da própria mudança lado esquerdo dependendo do que você retornar de um método no lado direito.

Não é possível.

Daí a minha resposta.

Respondeu 10/12/2008 em 10:39
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more