Pergunta

Eu estou usando o C# da Microsoft, o Unity framework.Eu não tenho muita certeza de como resolver este problema.Ele provavelmente tem algo a ver com a minha falta de entendimento de DI com o Unity.

O meu problema pode ser resumido usando o seguinte código de exemplo:

class Train(Person p) { ... }

class Bus(Person p) { ... }

class Person(string name) { ... }

Person dad = new Person("joe");
Person son = new Person("timmy");

Quando eu chamo o método de resolução de Ônibus como posso ter a certeza de que a Pessoa 'filho' com o nome 'timmy' é injetado e quando a resolução de Trem como posso ter a certeza de que a Pessoa de "pai", com o então nome de 'joe' é resolvido?

Eu estou pensando em talvez usar instâncias nomeadas?Mas eu estou em uma perda.Qualquer ajuda seria apreciada.

Como um aparte, eu prefiro não criar um IPerson interface.

Foi útil?

Solução

Uma maneira de resolver isso seria usar um construtor de injeção com um registro nomeado.

// Register timmy this way  
Person son = new Person("Timmy");  
container.RegisterInstance<Person>("son", son);  

// OR register timmy this way  
container.RegisterType<Person>("son", new InjectionConstructor("Timmy"));  

// Either way, register bus this way.  
container.RegisterType<Bus>(new InjectionConstructor(container.Resolve<Person>("son")));  

// Repeat for Joe / Train

Outras dicas

A menos que você se registre respectivamente "Joe" e "Timmy" como dependências nomeadas, não pode ter certeza de que "Timmy" é injetado no SchoolBus. De fato, se você tentar registrar duas instâncias da mesma classe que dependências sem nome, terá uma configuração ambígua e não poderá resolver Person de forma alguma.

Em geral, se você precisar registrar muitas instâncias nomeadas, provavelmente está seguindo o DI da maneira errada. A idéia principal de DI é resolver Serviços de domínio mais do que Objetos de domínio.

A idéia principal de DI é fornecer um mecanismo que permite resolver Tipos abstratos (interfaces ou classes abstratas) em tipos de concreto. Seu exemplo não tem tipos abstratos, por isso não faz muito sentido.

Marca Seeman, deu certo.E eu simpatizo com a sua confusão.Eu passei por ele, quando eu aprendi a usar automática de contêineres de injeção de dependência.O problema é que existem muitos válido e razoável maneiras de criar e usar objetos.Mas somente algumas dessas abordagens de trabalho com sistema automático de dependência injectorion recipientes.

Minha história pessoal:Eu aprendi OO princípios de construção do objeto e de Inversão De Controle muito antes de eu aprendi como usar a Inversão de Controle recipientes, como a Unidade ou o Castelo de Windsor recipientes.Adquiri o hábito de escrever código como este:

public class Foo
{
   IService _service;
   int _accountNumber;

   public Foo(IService service, int accountNumber)
   {
      _service = service;
      _accountNumber = accountNumber;
   }
   public void SaveAccount()
   {
       _service.Save(_accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service(),1234);
        foo.Save();
     }
}

Neste projeto, a minha classe Foo é responsável por contas de poupança para o banco de dados.Ele precisa de um número de conta para fazer o que e um serviço para fazer o trabalho sujo.Este é um pouco semelhante à cimentadas classes fornecido acima, onde cada objeto leva alguns valores exclusivos no construtor.Isso funciona bem quando você instanciar objetos com seu próprio código.Você pode passar valores corretos na hora certa.

No entanto, quando aprendi sobre automática de contêineres de injeção de dependência, descobri que eu não era mais instanciar Foo pela mão.O recipiente seria instanciar os argumentos do construtor para mim.Esta foi uma grande comodidade para os serviços como IService.Mas, obviamente, não funciona tão bem para os números e cadeias de caracteres e o como.Nesses casos, o que iria fornecer um valor padrão (como o zero para um número inteiro).Em vez disso, eu tinha sido acostumado a passar no contexto específico de valores como número de conta, nome, etc...Então eu tive que adaptar o meu estilo de codificação e design de ser como este:

public class Foo
{
   IService _service;
   public Foo(IService service)
   {
      _service = service;
   }
   public void SaveAccount(int accountNumber)
   {
       _service.Save(accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service());
        foo.Save(1234);
     }
}

Parece que tanto os Foo classes são válidos desenhos.Mas o segundo é utilizável com sistema automático de injeção de dependência, e o primeiro não.

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