【问题标题】:Configuring Ninject配置忍者
【发布时间】:2011-07-08 17:07:07
【问题描述】:

在与 Remo Gloor(主要开发人员)讨论了我们的 Ninject 配置 .NET memory profiling / risks for leaks / Ninject / Direct delegate roots 之后,我想弄清楚如何为 ASP.NET 网络表单应用程序正确配置它。

我们目前有一个要求,我们正在执行以下操作:

Bind<ISearchService>()
    .ToMethod(ctx => new BaseSearchService(ctx.Kernel.GetDefault<IDataRetrievalService>()))
    .InSingletonScope()
    .Named("BaseSearchService");

Bind<ISearchService>()
    .ToMethod(ctx => new HttpSearchService(
        ctx.Kernel.GetNamedOrDefault<ISearchService>("BaseSearchService"),
        HttpContext.Current))
    .InRequestScope();

GetNamedOrDefault 是我们拥有的扩展方法:

public static T GetDefault<T>(this IKernel kernel)
{
    return kernel.Get<T>(m => m.Name == null);
}

public static object GetDefault(this IKernel kernel, Type type)
{
    return kernel.Get(type, m => m.Name == null);
}

public static T GetNamedOrDefault<T>(this IKernel kernel, string name)
{
    T result = kernel.TryGet<T>(name);

    if (result != null)
        return result;

    return kernel.GetDefault<T>();
}

public static object GetNamedOrDefault(this IKernel kernel, Type type, string name)
{
    var result = kernel.TryGet(type, name);

    if (result != null)
        return result;

    return kernel.GetDefault(type);
}

我们如何最好地在 Ninject 中表现这一点?我们是否应该使用“WhenParentNamed”并让 Ninject 决定将什么对象传递给构造函数?

同样,我们如何绑定当前的 HttpContext.Current 对象,以便 Ninject 知道在构造函数将 HttpContext 对象作为其参数之一时使用它?应该和这里看到的一样吗?

https://github.com/ninject/ninject.web.mvc/blob/master/mvc3/src/Ninject.Web.Mvc/MvcModule.cs

如果我们使用请求范围,我们是否应该使用 OnePerRequestModule 并在应用程序的 Web.config 中进行配置?

我们是否也应该使用:

https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/NinjectHttpApplication.cs

为了确保我们的对象被正确处理?

这对某些人来说可能看起来很简单,但我只想说明每个人都采取的方法。

谢谢

【问题讨论】:

    标签: .net asp.net dependency-injection ninject


    【解决方案1】:

    如果使用某些条件绑定(例如,WhenParentNamed、WhenClassHas、WhenTargetHas 或自定义When)进行装饰,则是最好的方法。

    Bind<ISearchService>()
      .To<BaseSearchService>()
      .InSingletonScope()
      .WhenParentNamed("HttpServiceDecorator");
    
    Bind<ISearchService>()
        .To<HttpSearchService>()
        .Named("HttpServiceDecorator")
        .InRequestScope();
    
    Bind<HttpContext>().ToMethod(ctx => HttpContext.Current);
    

    获取服务的最佳方式是将其注入到需要它的类的构造函数中。接收 HttpSearchService 的实例没有什么特别必要的。它将作为默认值传递。

    从 Ninject.Web 2.2 开始,默认使用 OnePerRequestModule。所以不需要改变。

    为即将发布的 Ninject 2.4 版本引入了 Ninject.Web.Common。它是所有 Web 扩展使用的基础组件。这意味着只要您继续使用 2.2,就不能使用它。一旦切换到 2.4(或 2.3 开发版本)就必须使用它。

    【讨论】:

    • 感谢 Remo - 我想要实现的只是为我的装饰器模式实现配置绑定。我希望始终在内核或服务定位器上使用没有名称的 Get。无论返回什么都将由配置决定。我已经通过WhenInjectedInto 条件实现了这一点,但目前看不到上述内容将如何工作。我想我需要使用名称请求它 - HttpServiceDecorator?
    • 不,您不必指定名称。 HttpServiceService 将被返回,因为它是无条件的。这个名字只是元数据,它自己绝对不会死。同时摆脱 ServiceLocation 并开始使用 Ninject 作为 IoC 容器。请参阅blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspxTheNinject.Web 扩展将允许您创建一个设计,其中您需要知道容器的唯一地方就是配置。
    猜你喜欢
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多