Инъекция конструктора в 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 являются допустимыми конструкциями. Но второй можно использовать с автоматической инъекцией зависимостей, а первый-нет.