Unity InjectionConstructor для многопараметрического конструктора, переопределяющего только один
У меня есть класс с конструктором, подобным этому:
public class Bar
{
public Bar(IFoo foo, IFoo2 foo2, IFoo3 foo3, IFooN fooN, String text)
{
}
}
Я хочу зарегистрировать Bar в Unity и указать значение для текста:
unity.RegisterType<Bar, Bar>(new InjectionConstructor("123"));
Однако я не могу этого сделать, потому что для Bar нет единого конструктора параметров.
Есть ли способ предоставить значение для текста без указания всех других параметров как ResolvedParameter<IFooN>
и т.д. Мне действительно это не нравится, много кода, и каждый раз, когда я меняю конструктор Bar, мне нужно добавить другой ResolvedParameter
Ответы
Ответ 1
Единство не может сделать это из коробки. Лучшее, что вы можете сделать, это:
container.RegisterType<Bar>(
new InjectionConstructor(
typeof(IFoo), typeof(IFoo2), typeof(IFoo3), typeof(IFooN), "123"));
Или вы можете использовать SmartConstructor
, предоставляемый проектом TecX. Это сообщение в блоге описывает некоторый фон.
Регистрация будет выглядеть так:
container.RegisterType<Bar>(new SmartConstructor("text", "123"));
Ответ 2
public void Register<TFrom>(params object[] constructorParams) where TFrom : class
{
_container.RegisterType<TFrom>(new InjectionConstructor(constructorParams));
}
Ответ 3
Раньше я делал это, как описано в ответе выше (это с помощью InjectionConstructor
). Проблема в том, что если сигнатура конструктора изменяется, но InjectionConstructor
не обновляется, то мы узнаем об этом только во время выполнения. Я думаю, что есть более чистый способ сделать это, не вдаваясь в детали подписи конструктора. Вот как это делается:
public interface IBar
{
void DoSomethingWithBar();
}
public interface IMyStringPrameterForBar
{
string Value { get; }
}
public class MyStringPrameterForBar : IMyStringPrameterForBar
{
public string Value { get; }
public MyStringPrameterForBar(string value) => Value = value;
}
public class Bar : IBar
{
public Bar(IFoo foo, IFoo2 foo2, IFoo3 foo3, IFooN fooN, IMyStringPrameterForBar text)
{
}
public void DoSomethingWithBar() {}
}
Затем при регистрации интерфейсов просто добавьте:
unity.RegisterType<IFoo, Foo>();
unity.RegisterType<IFoo2, Foo2>();
unity.RegisterType<IFooN, FooN>();
unity.RegisterInstance(new MyStrignPrameterForBar("123"));
unity.RegisterType<IBar, Bar>();
Это все. если завтра Bar
потребуется принять больше или меньше параметров, то после добавления или удаления дополнительного Foo<N + 1>
Unity все равно будет автоматически создавать Bar
.
PS Я не думаю, что интерфейс IMyStringPrameterForBar
действительно необходим. Тем не менее, я предпочитаю видеть только интерфейсы в регистрациях Unity, потому что их гораздо проще крутить во время тестов и/или для любых других целей.