Инъекция конструктора в C# / Unity?

Я использую C# с Unity framework Microsoft. Я не совсем уверен, как решить эту проблему. Вероятно, это связано с моим непониманием Ди с Unity.

мою проблему можно суммировать, используя следующий пример кода:

class Train(Person p) { ... }

class Bus(Person p) { ... }

class Person(string name) { ... }

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

когда я вызываю метод resolve на автобусе, как я могу быть уверен, что человек " сын "с именем" Тимми "вводится и при разрешении поезда, как я могу быть уверен, что человек "папа" с именем " Джо " является решен?

Я думаю, может быть, использовать именованные экземпляры? Но я в растерянности. Любая помощь будет оценена.

в стороне, я бы предпочел не создавать интерфейс IPerson.

3 ответов


один из способов решить эту проблему-использовать конструктор инъекций с именованной регистрацией.

// 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

Если вы не зарегистрируете соответственно "Джо" и "Тимми" как именованные зависимости, вы не можете быть уверены, что "Тимми" вводится в Schoolbus. Фактически, если вы попытаетесь зарегистрировать два экземпляра того же класса, что и неназванные зависимости, у вас будет неоднозначная настройка, и вы не сможете разрешить Person на всех.

В общем, если вам нужно зарегистрировать много именованных экземпляров, вы, вероятно, собираетесь о DI в неправильном направлении. Основная идея DI-решить Доменных Служб больше, чем Объекты Домена.

основная идея DI-предоставить механизм, который позволяет разрешить абстрактные типы (интерфейсы или абстрактные классы) в конкретных видах. В вашем примере нет абстрактных типов, поэтому это не имеет большого смысла.


Марк Симан правильно понял. И я сочувствую вашему замешательству. Я сам прошел через это, когда научился использовать автоматические контейнеры для инъекций зависимостей. Проблема в том, что существует множество допустимых и разумных способов проектирования и использования объектов. Но только некоторые из этих подходов работают с автоматическими контейнерами injectorion зависимостей.

моя личная история: я узнал ОО принципы построения объектов и инверсии управления задолго до того, как я узнал, как использовать инверсию контейнеров контроля как контейнеры единства или Виндзора замка. Я приобрел привычку писать код следующим образом:--3-->

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

в этом дизайне мой класс Foo отвечает за сохранение учетных записей в базе данных. Для этого нужен номер счета и услуга для выполнения грязной работы. Это несколько похоже на указанные выше конкретные классы, где каждый объект принимает некоторые уникальные значения в конструкторе. Это отлично работает, когда вы создаете объекты с помощью собственного кода. Вы можете передать соответствующие значения в нужное время.

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

похоже, что оба класса Foo являются допустимыми конструкциями. Но второй можно использовать с автоматической инъекцией зависимостей, а первый-нет.