2011-07-19 25 views
5

所以,让我们说我有一个接口IThingFactory依赖注入:如何配置接口绑定包

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

现在,让我们说我有一个具体的实现,从数据库中检索Thing秒。现在,我们还要说一个具体的实现,它包装现有的IThingFactory,并在打包IThingFactory之前检查Thing是否存在于内存缓存中。喜欢的东西:

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容器,这样我可以注入或删除缓存代理这样,或者说,记录的东西,或者(插入这里)?

回答

5

你可以做线沿线的东西:

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

这将让消费者并不需要指定一个name属性,而且还比较容易进一步提高。如果你以后想添加用于记录一个额外的“装饰”层,你可以这样做:

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

不是最漂亮的,但很有效。

+0

甚至不知道存在WhenInjectedInto()方法。谢谢! – FMM

2

DI框架的好处之一是你不必做这样的事情。 Ninject有多种可用于指定对象生命周期的范围。它会为你处理缓存和东西。

在这里阅读更多:http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/

+0

不完全是我问的。我熟悉Ninject的对象范围,并且我在基于MVC的应用程序中充分利用了请求范围和单例范围。你的建议解决了我设计的例子,但是忽略了问题的关键。如何配置一个绑定,以便像上面那样“包装”一个接口? – FMM

+0

像这样:'BindToFactory ()。InRequestScope(); ' – Mrchief

+0

忘了提及,如果你使用'BindToFactory()',你需要连接你自己的提供者 - 调整你的'CachedThingFactory'来实现'IProvider'(更多在这里https://github.com/ninject/ninject/维基/提供商%2C-工厂方法和最激活上下文)。你也可以使用'.ToMethod()'方法。 – Mrchief

2

我想你正在寻找一个名为结合,这里记载:

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; 
} 
+0

我已经熟悉命名绑定;然而,用字符串类型的属性来装饰我的类感觉很脏。 – FMM

+0

不太清楚你的问题:-)。值得一读:http://eeichinger.blogspot.com/2009/12/springnet-aop-behind-scenes-1.html从“装饰者”到“aop”。 – Andreas

+0

有趣的阅读,谢谢!他在下一个博客中指出的IMethodInterceptor接口感觉更加肮脏,尽管=) – FMM