Configuring Ninject

2019-07-20 05:41发布

Following a discussion with Remo Gloor (main dev) about our Ninject configuration, .NET memory profiling / risks for leaks / Ninject / Direct delegate roots, I'd like to get some clarity on configuring it properly for an ASP.NET webforms application.

We have a requirement currently where we are doing the following:

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 is an extension method we have:

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

How best are we to represent this in Ninject? Should we use "WhenParentNamed" and let Ninject decide what object to pass to the constructor?

Likewise, how do we bind the current HttpContext.Current object so that Ninject knows to use that whenever a constructor takes a HttpContext object as one of its parameters? Should it be the same as seen here?

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

If we are making use of the request scope, should we be using the OnePerRequestModule and configuring this in the Web.config of the application?

Should we also use:

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

To ensure our objects are disposed properly?

This may seem quite simplistic to some but I just want to be clear on the approach everyone takes.

Thanks

1条回答
成全新的幸福
2楼-- · 2019-07-20 06:13

In case of decoration using some conditional binding (e.g. WhenParentNamed, WhenClassHas, WhenTargetHas or a custon When) is the best way to go.

Bind<ISearchService>()
  .To<BaseSearchService>()
  .InSingletonScope()
  .WhenParentNamed("HttpServiceDecorator");

Bind<ISearchService>()
    .To<HttpSearchService>()
    .Named("HttpServiceDecorator")
    .InRequestScope();

Bind<HttpContext>().ToMethod(ctx => HttpContext.Current);

The best way to get the service is to inject it to the constructor of the class that needs it. There is nothing special necessary to receive an instance of HttpSearchService. It will be passed as default.

Since Ninject.Web 2.2 the OnePerRequestModule is used by default. So no change is required.

Ninject.Web.Common is introduced for the upcomming Ninject 2.4 release. It is a base component used by all web extensions. This means as long as you stay on 2.2 you must not use it. As soon as you switch to 2.4 (or a 2.3 development build) will have to use it.

查看更多
登录 后发表回答