Alternativas para o “usando” palavra-chave directiva em C #?
-
05-07-2019 - |
Pergunta
Acabei de assistir um episódio de Bob Martin em NDC onde ele disse "usando" directivas em C # no topo de uma página são ruins por causa do apertado acoplamento eles criam / implicam entre componentes.
O que maneira estão lá para usar .dlls externos sem adicionar uma referência de projeto e uma usando declaração?
Eu me lembro V6 usado para permitir que você criar um objeto pela cadeia do ProgId - não tenho certeza que é a técnica que eu estou procurando, mas é um exemplo de uma linguagem que não precisava de uma referência de projeto para usar uma dll.
EDIT: Aqui está um link para a conferência . Desculpe eu não tenho a cotação ou minuto no presenation, eu vou pela memória.
Solução
Não é o utilizando-se instrução que é ruim -. É se você começar muitos deles
Uma declaração como using System;
raramente é um problema em si, mas se você tiver lotes (eu diria que mais de 3-6, dependendo de quais) no mesmo arquivo de código, que poderia ser um indicação de acoplamento forte .
Você poderia muito bem aplicar uma regra semelhante de ouro para o número de referências em um projeto em si.
A solução para acoplamento forte é programação para as interfaces e Dependency Injection (DI).
A forma ProgId de fazer as coisas que você pode se lembrar de VB era simplesmente COM em ação. Em essência, você usou que ProgId para obter uma referência a uma instância que implementou a interface desejada. A desvantagem foi que isso só funcionou quando o objeto COM foi universalmente registrado. Lembre-se dll inferno?
Você ainda pode aplicar o mesmo princípio usando certos sabores de DI, apenas que agora a interface é um tipo .NET e não definidos no IDL, e você precisa de algum tipo de DI Container para fornecer a implementação concreta.
Outras dicas
Eu acredito que Bob Martin é realmente referindo-se precoce versus ligação tardia.
Em .NET ligação tardia é possível através de reflexão e, mais especificamente, a classe Activator que permite a criação de um tipo em uma montagem externa usando um nome ou nome de assemblagem.
Normalmente, usando diretivas (não utilizando a instrução) andam de mãos dadas com referência direta um assembly externo. ie. Você adicionar uma referência a uma montagem e, em seguida, adicionar usando diretivas para evitar a necessidade de digitar a hierarquia namespace completo quando você usa os tipos externos.
Então, se você encontrar o seu código tem um grande número de diretivas usando na parte superior, é possível que você está fazendo referência muitos outros tipos diretamente e assim aumentar o acoplamento / dependência do seu código sobre esses tipos.
Eu acho que é por isso que Bob está se referindo a eles como ruim. A resposta para a pergunta "é este realmente ruim?" é muito subjetiva e dependente do contexto.
No entanto geral, de-acoplamento de componentes é quase sempre uma boa meta ter como objectivo na concepção de software. Isso é porque ele permite que você altere partes de seu sistema com o mínimo impacto sobre o resto do sistema. Depois de ler um ou dois livros Bob Martins, eu esperaria que isso é o que ele está chegando.
using
é apenas um atalho para namespaces, eles não são referências a arquivos externos. Portanto, este não é apenas realmente fazendo sentido.
De qualquer forma, o que se pode fazer é ter uma DLL de interface (a DLL com apenas interfaces), para que você dinamicamente carregar e usar diferentes montagens e criar tipos (por meio de reflexão) que você pode lançar para as interfaces bem conhecidos. Esta é a maneira correta de afrouxamento referências externas, mantendo os benefícios da linguagem fortemente digitado e ligação antecipada.
Tenha um olhar para o Assembléia AppDomain aulas para conjuntos de carga, e Activator para criar instâncias do tipo pelo nome.
Você pode usar reflexão:
// Load the assembly
Assembly assembly = Assembly.LoadFrom(@"c:\path\Tools.dll");
// Select a type
Type type = assembly.GetType("Tools.Utility");
// invoke a method on this type
type.InvokeMember("SomeMethod", BindingFlags.Static, null, null, new object[0]);
Você pode fazer o que você está se referindo por meio de reflexão. Você pode carregar o assembly em tempo de execução, e refletir através dele para obter as classes etc. e chamá-los de forma dinâmica.
Pessoalmente, eu não faria isso, porém ao acoplamento evitar. Para mim, isso é um mau uso da reflexão, e eu seria muito melhor adicioná-lo ao projeto e referenciá-lo, a menos que haja uma razão específica por que não fazê-lo. Reflexão adiciona sobrecarga para o sistema, e você não terá a vantagem de segurança tempo de compilação.