【问题标题】:How to set up Ninject DI to create Hyprlinkr RouteLinker instances如何设置 Ninject DI 以创建 Hyprlinkr RouteLinker 实例
【发布时间】:2012-10-16 05:13:30
【问题描述】:

我有一个 MVC4 Web API 项目,我利用 Mark Seemann 的 Hyprlinkr 组件生成链接资源的 Uris。 (例如客户 -> 地址)。

我已经按照 Mark 的 Dependency injection with Web API 指南(针对 Ninject 进行适当更改)位我不太清楚应该如何将 IResourceLinker 注入我的控制器。

按照 Mark 的 guide 我的 IHttpControllerActivator.Create 创建方法如下所示:

IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
    var controller = (IHttpController) _kernel.GetService(controllerType);

    request.RegisterForDispose(new Release(() => _kernel.Release(controller)));

    return controller;
}

Hyprlinkr readme 建议在此方法中创建RouteLinker。不幸的是,我不确定如何向 Ninject 注册。

我不能像下面这样绑定,因为这会导致多个绑定:

_kernel.Bind<IResourceLinker>()
    .ToMethod(context => new RouteLinker(request))
    .InRequestScope();

我有这样的重新绑定工作:

_kernel.Rebind<IResourceLinker>()
    .ToMethod(context => new RouteLinker(request))
    .InRequestScope();

但我担心更改 ninject 绑定图对于每个请求都可能是一件坏事。

实现这一目标的最佳方法是什么?


根据Paige Cook的要求更新

我在这里使用重新绑定:

IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
    _kernel.Rebind<IResourceLinker>()
        .ToMethod(context => new RouteLinker(request))
        .InRequestScope();

    var controller = (IHttpController) _kernel.GetService(controllerType);

    request.RegisterForDispose(new Release(() => _kernel.Release(controller)));

    return controller;
}

IHttpControllerActivator.Create 在每个请求上都会被调用。其余绑定以标准方式进行,按标准我的意思是在使用Ninject.MVC3 nuget 包生成的类中。

我的控制器如下所示:

public class CustomerController : ApiController
{
    private readonly ICustomerService _customerService;
    private readonly IResourceLinker _linker;

    public CustomerController(ICustomerService customerService, IResourceLinker linker)
    {
        _customerService = customerService;
        _linker = linker;
    }

    public CustomerModel GetCustomer(string id)
    {
        Customer customer = _customerService.GetCustomer(id);
        if (customer == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }

        return
            new CustomerModel
                {
                    UserName       = customer.UserName,
                    Firstname      = customer.Firstname,
                    DefaultAddress = _linker.GetUri<AddressController>(c => c.Get(customer.DefaultAddressId)),
                };
    }
}

【问题讨论】:

  • 您能否向我们展示您在上下文中执行 _kernel.Rebind 调用的位置以及典型控制器的外观?
  • 感谢页面,我添加了更多信息。
  • 如需在温莎城堡中使用此功能,请参见此处:stackoverflow.com/q/10854701/126014

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


【解决方案1】:

注册一个委托函数给你链接器

_kernel.Bind<Func<HttpRequestMessage, IResourceLinker>>()
    .ToMethod(context => (request) => new RouteLinker(request));

注入委托

readonly Func<HttpRequestMessage, IResourceLinker> _getResourceLinker;

public controller(Func<HttpRequestMessage, IResourceLinker> getResourceLinker) {

    _getResourceLinker = getResourceLinker;
}

在你的行动中使用

public async Task<Thingy> Get() {

    var linker = _getResourceLinker(Request);
    linker.GetUri( ... )

}

【讨论】:

  • 您好安东尼,感谢您的回复。该解决方案有效,但我无法从构造函数中使用它,因为此时 Request 对象为空。我可以在 Actions 中使用它。
  • @JamesSkimming:+1 好整洁的答案。您可能还会发现 Ninject.Extensions.Factory 很有用,因为它可以做一些这样的事情(隐含的 ToMethod lambda)。显然,这对于这个问题来说太过分了,但隐藏了这一点!
  • 如果您在对象图中需要一个 RouteLinker 实例(即不是来自 ApiController 实例内部)怎么办?在这种情况下,您没有任何 HttpRequestMessage 可以用来调用委托...另外,请参阅我对 在 ApiController 中的情况的回答。
【解决方案2】:

如果您只需要使用来自 ApiController 派生类的 RouteLinker,您实际上并不需要经历所有的 DI 箍。

您可以像这样在控制器中创建它:

var linker = new RouteLinker(this.Request);

IMO,当您需要更靠后的 RouteLinker 时,首先将 DI 与 RouteLinker 一起使用会变得很有价值 - 但话又说回来,我也只将 RouteLinker 用作Concrete Dependency...

【讨论】:

    【解决方案3】:

    感谢您添加代码示例。根据您发布的内容,您遇到了绑定/重新绑定问题,因为您每次都在 IHttpControllerActivtor.Create 方法中发出 _kernel.Bind&lt;IResourceLinker&gt;

    您需要移动 _kernel.Bind&lt;IResourceLinker&gt; 以进行注册,就像您在

    ...标准方式,标准是指在使用 Ninject.MVC3 nuget 包生成的类中。

    应该不需要多次绑定IResourceLinker,这就是为什么要获得多个实例,因为每次 IHttpControllerActivator 创建控制器时都会触发绑定。

    更新: 抱歉,我错过了将 HttpRequestMessage 作为构造函数参数的需要,我会选择 Anthony Johnson 对此的回答。

    【讨论】:

    • 嗨页面,感谢您的回复。将绑定与其余绑定放在一起不起作用,因为具体类 RouteLinker 在其构造函数上需要 HttpRequestMessage
    • +1 因为您确定了主要问题,并把整个事情弄清楚了,可以回答。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多