WebApi2控制器方法

时间:2017-07-14 17:34:04

标签: c# asp.net-web-api dependency-injection ninject

我正在使用Ninject和以下软件包:

  • Ninject
  • Ninject.MVC5
  • Ninject.Web.Common(和Common.WebHost)
  • Ninject.Web.WebApi(和WebApi.WebHost)

我有一个WebApi2控制器,如下所示。我的Get()方法必须具有高效性,并且不依赖于IMyFooService的值,因此在请求Get()时,我不关心它是否被注入。

问题:

只有在调用某些api方法时,我才有选择性地绑定接口的方法吗?是通过使用属性还是......?

public class FooController : ApiController {

    public IMyFooService fooService;

    public FooController(IMyFooService fooService) {
        this.fooService = fooService;
    }

    [NonDependent] // Don't really care about the value of fooService
    public JsonResult Get() {}

    [Dependent] // Must have valid dependency injection
    public async Task<JsonResult> Post([FromBody] IList foos) {
        var didMyFoo = this.fooService.DoTheFoo();
    }
}

这是我的NinjectWebCommon.cs

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IMyFooService>().To<MyConcreteService>().InRequestScope();
}

我注意到To<T>()有很多.When()选项。也许我可以利用这个来说.When(/* Controller = Foo, Action = Post */)

2 个答案:

答案 0 :(得分:4)

最简单,也可能是最简洁的方法是使用完全针对此用例的Lazy<T> - 引用文档:

  

使用延迟初始化来推迟创建大型或   资源密集型对象,或资源密集型的执行   任务,特别是当这种创建或执行可能不会发生时   在该计划的整个生命周期中。

支持Lazy<T>注入Ninject.Extensions.Factory(另见Lazy<T>上的Wiki页面)。安装它nuget package,您应该准备好注入Lazy<T>

按如下方式调整控制器的代码:

public class FooController : ApiController {

    public Lazy<IMyFooService> fooService;

    public FooController(Lazy<IMyFooService> fooService) {
        this.fooService = fooService;
    }

    public JsonResult Get() {}

    public async Task<JsonResult> Post([FromBody] IList foos) {
        var didMyFoo = this.fooService.Value.DoTheFoo();
    }
}

请注意,.Value上的 Lazy<T> 属性访问了实际服务。首次访问此属性时,将检索实例。

答案 1 :(得分:0)

前段时间已经提出了类似的问题。检查this。所以对于你的特殊情况你可以修改IsRouteValueDefined方法(你可以考虑一些更好的命名,我会建议像IsRoutePoitingTo这样的东西)从原始答案到这样的东西(你可能会重新审视,如果它适用于WebApi,但肯定有一个获得当前路线的方法):

public static bool IsRouteValueDefined(string controller, string action)
{
    var mvcHanlder = (MvcHandler)HttpContext.Current.Handler;
    var routeValues = mvcHanlder.RequestContext.RouteData.Values;
    var containsRouteKey = routeValues.ContainsKey(routeKey);
    if (routeValue == null)
        return containsRouteKey;

    return containsRouteKey &&
           routeValues["controller"].ToString().Equals(controller, StringComparison.InvariantCultureIgnoreCase) &&
           routeValues["action"].ToString().Equals(action, StringComparison.InvariantCultureIgnoreCase);
}

绑定看起来像:

kernel.Bind<IMyFooService>()
      .To<MyConcreteService>()
      .When(x=> IsRouteValueDefined("foo", "get"));

只是不确定&#34;得到&#34;对于ApiController,实际路由可以是http://website.com/foo/,如果是这样,只需使用string.Empty作为&#34; action&#34; PARAM。您可以使用您的特定项目进行检查。因为你不需要默认注射(原始答案中存在) - 我只是放弃了它。