Привязка одного класса к нескольким интерфейсам как singleton

У меня например 2 интерфейса IInterface1 и IInterface2,

public interface IInterface1 {...}
public interface IInterface2 {...} 

и одна реализация этих интерфейсов ImplClass.

public class ImplClass : IInterface1, IInterface2 {...}

Я должен быть уверен, что приложение имеет только один экземпляр ImplClass, который будет использоваться как IInterface1 и IInterface2. Я использую ninject для внедрения зависимостей. Итак, мой вопрос: соответствует ли приведенный ниже код моим требованиям?

...
Bind<IInterface1>().To<ImplClass>().Using<SingletonBehavior>();
Bind<IInterface2>().To<ImplClass>().Using<SingletonBehavior>();
...

Или этот код создаст 2 экземпляра ImplClass для каждого интерфейса?


person iburlakov    schedule 16.11.2010    source источник
comment
Дубликат stackoverflow.com/questions /3147996/   -  person Pete    schedule 16.11.2010
comment
@Pete, ты можешь проголосовать за закрытие (хороший звонок, кстати)   -  person Ruben Bartelink    schedule 12.09.2012


Ответы (4)


С Ninject вы можете сделать это:

var impl = new Impl();
container.Bind<IInt1>().ToMethod(c => impl);
container.Bind<IInt2>().ToMethod(c => impl);

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

container.Bind<Impl>().ToSelf().InSingletonScope();
container.Bind<IInt1>().ToMethod(c => c.Kernel.Get<Impl>());
container.Bind<IInt2>().ToMethod(c => c.Kernel.Get<Impl>()); 

Красиво и чисто.

person Steven    schedule 16.11.2010
comment
Мне это нравится. Вам не нужно настраивать класс как настоящий синглтон, но вы гарантируете, что всегда предоставляется только один экземпляр. - person KeithS; 16.11.2010
comment
-1 Не очень хорошее общее решение, так как каждое разрешение приводит к активации, см. stackoverflow.com/questions/3043441/ - person Ruben Bartelink; 12.09.2012
comment
(Лучший ответ, пока этот повторяющийся вопрос не исчезнет, ​​​​это stackoverflow.com/questions/10206049/ ) - person Ruben Bartelink; 12.09.2012
comment
См. ответ Даана ниже - Ninject v3 теперь дает вам более элегантный способ сделать это :) - person Efrain; 21.03.2016

Кажется, вы все еще используете Ninject 1.5. Я больше не имею в виду точный синтаксис, но он должен быть похож на следующий синтаксис версии 2.1:

kernel.Bind<I1>().ToMethod(ctx => ctx.Kernel.Get<Impl>());
kernel.Bind<I2>().ToMethod(ctx => ctx.Kernel.Get<Impl>()); 
kernel.Bind<Impl>().ToSelf().InSingletonScope();

Или, что еще лучше, используйте Ninject.Extensions.ContextPreservation, чтобы сохранить контекст.

kernel.Bind<Impl>().ToSelf().InSingletonScope();
kernel.BindInterfaceToBinding<I1, Impl>();
kernel.BindInterfaceToBinding<I2, Impl>();
person Remo Gloor    schedule 17.11.2010
comment
@JeffWalkerCodeRanger Пожалуйста, объясните - person Remo Gloor; 22.02.2012
comment
Проголосовал за, хотел бы перейти на отрицательный на основе дубликата stackoverflow.com/a/4195510/11635 (и те же проблемы с несколькими активациями) - person Ruben Bartelink; 12.09.2012

Вот как вы можете сделать это в одной строке кода:

Bind<IInterface1 ,IInterface2 ,ImplClass>().To<ImplClass>().InSingletonScope();

https://github.com/ninject/Ninject.Extensions.ContextPreservation/wiki/BindInterfaceToBinding

Требуется Ninject версии 3.

person Daan    schedule 24.03.2015

Я подозреваю, что это создаст два экземпляра.

Попробуйте, работает ли для вас следующая конструкция:

public class ImplClass : IInterface1, IInterface2
{
    public static readonly ImplClass Instance = new ImplClass();
}

Со следующей привязкой:

Bind<IInterface1>().ToMethod(c => ImplClass.Instance);
Bind<IInterface2>().ToMethod(c => ImplClass.Instance);
person Pieter van Ginkel    schedule 16.11.2010
comment
Хороший ответ и +1, но IMO часть преимущества инфраструктуры IoC заключается в том, что вы можете настроить одноэлементный объект без необходимости фактически определять структуру класса как одноэлементную (упрощая позже передумать или установить создать контейнер или заводскую регистрацию в другой среде). Что, если он просто инициализирует класс в классе Binding и зарегистрирует его как одноэкземплярную область видимости? (Я не очень хорошо разбираюсь в возможностях Ninject, но у Autofac с этим проблем не будет). - person KeithS; 16.11.2010