简体   繁体   English

依赖注入:如何配置接口绑定以进行包装

[英]Dependency Injection: How to configure interface bindings for wrapping

So, let's say I have an interface IThingFactory :所以,假设我有一个接口IThingFactory

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

Now, let's say I have a concrete implementation that retrieves Thing s from a database.现在,假设我有一个从数据库中检索Thing的具体实现。 Now, let's also say I have a concrete implementation that wraps an existing IThingFactory and checks for a Thing 's presence in, say, an in-memory cache before hitting the wrapped IThingFactory .现在,假设我有一个具体的实现,它包装了现有的IThingFactory并在命中包装的IThingFactory之前检查Thing是否存在于内存缓存中。 Something like:就像是:

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

How would I deal with a scenario like this using dependency injection with something like, say, Ninject, so that I could configure the DI container so that I can inject or remove a caching proxy like this, or, say, something that does logging, or (insert here)?我将如何使用依赖注入和 Ninject 之类的东西来处理这样的场景,以便我可以配置 DI 容器,以便我可以注入或删除这样的缓存代理,或者说,可以记录的东西,或(在此处插入)?

You can do something along the lines of:您可以执行以下操作:

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

This will let consumers not need to specify a name attribute, and is still relatively easy to further enhance.这样消费者就不需要指定名称属性了,进一步增强还是比较容易的。 If you later wanted to add an additional "decorator" layer for logging, you could do:如果您以后想为日志添加一个额外的“装饰器”层,您可以这样做:

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

Not the prettiest, but it works.不是最漂亮的,但它有效。

One of the benefits of DI framework is that you don't have to do things like these. DI 框架的好处之一是您不必做这些事情。 Ninject has various scopes that you can use to specify the lifetime of your objects. Ninject 有各种范围,您可以使用它们来指定对象的生命周期。 It'll handle caching and stuff for you.它会为你处理缓存和东西。

Read more here: http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/在此处阅读更多信息: http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/

I suppose you are searching for named binding, documented here:我想您正在搜索命名绑定,记录在这里:

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

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

and then接着

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

and for the consumer of the CachedThingFactory对于 CachedThingFactory 的消费者

public ThingFactoryConsumer([Named("TheCachedThing")] IThingFactory thingFactory)
{
   _thingFactory = thingFactory;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM