【问题标题】:Dependency Injection: How to configure interface bindings for wrapping依赖注入:如何配置接口绑定以进行包装
【发布时间】:2011-07-19 19:06:13
【问题描述】:

所以,假设我有一个接口IThingFactory

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

现在,假设我有一个从数据库中检索Things 的具体实现。现在,假设我有一个具体的实现,它包装了现有的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 容器,以便我可以注入或删除这样的缓存代理,或者说,记录,或者(在此处插入)?

【问题讨论】:

    标签: c# dependency-injection ninject ninject-2


    【解决方案1】:

    您可以按照以下方式做一些事情:

    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> ();
    

    不是最漂亮的,但它确实有效。

    【讨论】:

    • 甚至不知道存在WhenInjectedInto() 方法。谢谢!
    【解决方案2】:

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

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

    【讨论】:

    • 不完全是我要问的。我熟悉 Ninject 的对象作用域,并且在我的基于 MVC 的应用程序中大量利用了请求作用域和单例作用域。你的建议解决了我人为的例子,但错过了问题的重点。如何配置绑定以便我可以像上面一样“包装”接口?
    • 类似这样的东西:BindToFactory&lt;IThing, CachedThingFactory&gt;().InRequestScope();
    • 忘了说,如果你使用BindToFactory(),你需要连接你自己的提供者——调整你的CachedThingFactory来实现IProvider(更多在这里github.com/ninject/ninject/wiki/…)。你也可以使用.ToMethod()的方法。
    【解决方案3】:

    我想您正在搜索命名绑定,记录在这里:

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

    【讨论】:

    • 我已经熟悉命名绑定;但是,用字符串类型的属性装饰我的类感觉很脏。
    • 你的问题不太清楚:-)。值得一读:eeichinger.blogspot.com/2009/12/… 从“装饰者”到“aop”。
    • 有趣的阅读,谢谢!他在下一篇博客中提到的 IMethodInterceptor 接口感觉更脏,不过 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 2018-01-06
    • 2011-03-16
    • 2011-07-31
    • 2023-03-23
    • 2017-06-10
    相关资源
    最近更新 更多