Подтвердить что ты не робот

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

4b9b3361

Ответ 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, потому что их гораздо проще крутить во время тестов и/или для любых других целей.