Внедрение зависимостей: как настроить привязки интерфейса для переноса - PullRequest
5 голосов
/ 19 июля 2011

Итак, допустим, у меня есть интерфейс IThingFactory:

public interface IThingFactory
{
    Thing GetThing(int thingId);
}

Теперь, скажем, у меня есть конкретная реализация, которая извлекает Thing s из базы данных.Теперь, давайте также скажем, что у меня есть конкретная реализация, которая упаковывает существующий IThingFactory и проверяет наличие Thing, скажем, в кеше в памяти, прежде чем нажать на обернутый IThingFactory.Что-то вроде:

public class CachedThingFactory : IThingFactory
{
    private IThingFactory _wrapped;
    private Dictionary<int, Thing> _cachedThings;

    public CachedThingFactory(IThingFactory wrapped)
    {
        this._wrapped = wrapped;
        _cachedThings = new Dictionary<int,Thing>();
    }

    public Thing GetThing(int thingId)
    {
        Thing x;
        if(_cachedThings.TryGetValue(thingId, out x))
            return x;

        x = _wrapped.GetThing(thingId);

        _cachedThings[thingId] = x;

        return x;
    }
}

Как бы я справился с таким сценарием, используя инъекцию зависимостей с чем-то вроде, скажем, Ninject, чтобы я мог настроить контейнер DI так, чтобы я мог внедрять или удалять прокси-сервер кэшированиякак это, или, скажем, что-то, что делает журналирование, или (вставьте сюда)?

Ответы [ 3 ]

5 голосов
/ 20 июля 2011

Вы можете сделать что-то вроде:

Bind<IThingFactory> ().To<DefaultThingFactory> ().WhenInjectedInto<CachedThingFactory> ();
Bind<IThingFactory> ().To<CachedThingFactory> ();

Это позволит потребителям не указывать атрибут имени, и его относительно легко усовершенствовать.Если вы позже захотите добавить дополнительный слой «оформитель» для ведения журнала, вы можете сделать:

Bind<IThingFactory> ().To<DefaultThingFactory> ().WhenInjectedInto<LoggingThingFactory> ();
Bind<IThingFactory> ().To<LoggingThingFactory> ().WhenInjectedInto<CachedThingFactory> ();
Bind<IThingFactory> ().To<CachedThingFactory> ();

Не самый красивый, но он работает.

2 голосов
/ 19 июля 2011

Полагаю, вы ищете именованную привязку, задокументированную здесь:

https://github.com/ninject/ninject/wiki/Contextual-Binding

Bind<IThingFactory>().To<CachedThingFactory>().Named("TheCachedThing");
Bind<IThingFactory>().To<DefaultThingFactory >().Named("ThePureThing");

, а затем

public CachedThingFactory([Named("ThePureThing")] IThingFactory wrapped)
{
    this._wrapped = wrapped;
    _cachedThings = new Dictionary<int,Thing>();
}

и для потребителя CachedThingFactory

public ThingFactoryConsumer([Named("TheCachedThing")] IThingFactory thingFactory)
{
   _thingFactory = thingFactory;
}
2 голосов
/ 19 июля 2011

Одним из преимуществ инфраструктуры DI является то, что вам не нужно делать такие вещи.У Ninject есть различные области, которые вы можете использовать, чтобы указать время жизни ваших объектов.Он будет обрабатывать кеширование и прочее для вас.

Подробнее читайте здесь: http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/

...