Создание экземпляра с помощью Ninject с дополнительными параметрами в конструкторе


Я решил начать использовать Ninject и столкнуться с проблемой. Скажем, у меня есть следующий сценарий. У меня есть IService интерфейс и 2 класса, реализующие этот интерфейс. А также у меня есть класс, который имеет конструктор getting IService и int. Как я могу создать экземпляр этого класса с помощью Ninject (я не хочу подключать этот int, я хочу передавать его каждый раз, когда я получаю экземпляр)?

вот некоторый код, иллюстрирующий ситуацию:

interface IService
{
    void Func();
}

class StandardService : IService
{
    public void Func()
    {
        Console.WriteLine("Standard");
    }
}

class AlternativeService : IService
{
    public void Func()
    {
        Console.WriteLine("Alternative");
    }
}


class MyClass
{
    public MyClass(IService service, int i)
    {
        this.service = service;
    }

    public void Func()
    {
        service.Func();
    }

    IService service = null;
}
class Program
{
    static void Main(string[] args)
    {
        IKernel kernel = new StandardKernel(new InlineModule(
            x => x.Bind<IService>().To<AlternativeService>(),
            x => x.Bind<MyClass>().ToSelf()));

        IService service = kernel.Get<IService>();

        MyClass m = kernel.Get<MyClass>();
        m.Func();
    }
}
1 62

1 ответ:

The With.ConstructorArgument существовал в 1.0 для этой цели. В версии 2.0 синтаксис немного изменился:- С.Параметры.ConstructorArgument с ninject 2.0

посмотреть ввести значение в введенную зависимость для получения более подробной информации и примеров того, как использовать контекст, поставщиков и аргументы, чтобы передать такие вещи более правильно.

EDIT: поскольку Стивен решил притвориться, что мой комментарий не имеет отношения к делу, мне лучше прояснить, что я говорю с некоторыми примерами (для 2.0):

MyClass m = kernel.Get<MyClass>( new ConstructorArgument( "i", 2) );

что для моих глаз очень ясно и точно говорит о том, что происходит.

если вы находитесь в положении, когда вы можете определить параметр более глобальным способом, вы можете зарегистрировать поставщика и сделать это следующим образом:

class MyClassProvider : SimpleProvider<MyClass>
{
    protected override MyClass CreateInstance( IContext context )
    {
        return new MyClass( context.Kernel.Get<IService>(), CalculateINow() );
    }
}

и зарегистрировать его так:

x => x.Bind<MyClass>().ToProvider( new MyClassProvider() )

важно!CalculateINow() бит-это то, где вы бы поместили свою логику, как в первом ответе.

или сделать его более сложным, как это:

class MyClassProviderCustom : SimpleProvider<MyClass>
{
    readonly Func<int> _calculateINow;
    public MyClassProviderCustom( Func<int> calculateINow )
    {
        _calculateINow = calculateINow;
    }

    protected override MyClass CreateInstance( IContext context )
    {
        return new MyClass( context.Kernel.Get<IService>(), _calculateINow() );
    }
}

который вы зарегистрировали бы так:

x => x.Bind<MyClass>().ToProvider( new MyClassProviderCustom( (  ) => new Random( ).Next( 9 ) ) )

обновление: новые механизмы, которые показывают гораздо более совершенные модели с меньшим шаблоном, чем выше, воплощены в