API 方法调用时私有成员突然为空

问题描述 投票:0回答:3

发生奇怪的事情:在我的 Web api 中,我在使用 Ninject 解析时将存储库注入到控制器中。存储库存储在私有只读成员变量中。工作完美!当调用 api 方法时,我访问该变量 - 结果发现它突然变成了 null!

伪示例:

public class MyController : ApiController {

  private readonly IRepo _repo;

  public MyController(IRepo repo) {
     Guard.AgainstNullArgument("repo", repo); // guarding to 
                                                          // make sure it's not null
                                                          // (would throw ex)
     _repo = repo; <--- successfully injected
  }

  // calling this method
  public HttpResponseMessage TestMethod() {
     _repo.. <--- suddenly null
  }

}

我已经将问题追溯到一个微小的细节:控制器中的方法之一(不是被访问的方法)用一个自定义属性进行注释,该属性指示 ninject 使用工作单元拦截该方法。如果我去掉该属性,一切都会神奇地再次起作用。

UnitOfWorkAttribute.cs

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface)]
public class UnitOfWorkAttribute : Attribute
{
}

AttributeInterceptionStrategy.cs(用于ninject)

http://pastebin.com/Qg6tQWye

StartupConfig.cs(组合根、IoC 配置等)

http://pastebin.com/fcuSdujj

EfUnitOfWorkInterceptor.cs

public class EfUnitOfWorkInterceptor : SimpleInterceptor
{

    private readonly IUnitOfWork _unitOfWork;

    public EfUnitOfWorkInterceptor(IUnitOfWork unitOfWork)
    {
        Guard.AgainstNullArgument("unitOfWork", unitOfWork);
        _unitOfWork = unitOfWork;
    }

    protected override void AfterInvoke(IInvocation invocation)
    {
        if(!_unitOfWork.Commited)
            _unitOfWork.Commit();

        _unitOfWork.Dispose();
    }
}

编辑

我确实在各处都设置了断点来弄清楚发生了什么。在控制器上创建了一个析构函数,以确保整个类不会被垃圾化,并将只读成员更改为带有 getter/setter 的属性,我在 setter 上断点以检查它是否被分配了两次。根本没有发生任何可疑的事情。

编辑2

堆栈

http://pastebin.com/pQULHLT0

Ninject.Extensions.Interception.dll!Ninject.Extensions.Interception.Injection.Dynamic.DynamicMethodInjector.Invoke(object target = {EIT.Management.Configuration.Web.Api.Controllers.SetupGroupController}, object[] arguments = {object[2]})   Unbekannt
    Ninject.Extensions.Interception.dll!Ninject.Extensions.Interception.Invocation.Invocation.CallTargetMethod()    Unbekannt

编辑 3*

真实世界代码:http://pastebin.com/SqpR9KNR

c# asp.net-web-api dependency-injection ninject aop
3个回答
2
投票

真奇怪啊!我想也许你有另一个构造函数它没有设置你的_repo,然后是由它实例化的控制器的新实例。


0
投票

如果您使用 LinFu(您应该这样做,因为 DynamicProxy 仍然需要无参数构造函数),解决方案非常简单:只需创建用

UnitOfWorkAttribute
virtual
注解的方法即可。

我通过一些测试发现了这一点:经过一些尝试,我注意到如果你删除

plan.Add(new ProxyDirective());
,一切都会起作用。当然,拦截器没有被应用,但这表明代理类是罪魁祸首。


0
投票

Freds 的回答让我找到了我的问题,基本上是一个 DI 问题。 我有一个

BackgroundService
,它也实现了
IHealthCheck
接口,配置:

    services.AddHostedService<MyBackgroundServiceType>();
    services.AddHealthChecks().AddCheck<MyBackgroundServiceType>();

基本上添加了两个

MyBackgroundServiceType
实例,其中第二个实例从未被
host.RunAsync()
调用,因此也从未被初始化 - 但它确实被调用进行健康检查,导致与原始海报相同的问题。

我将配置更改为:

    services.AddSingleton<MyBackgroundServiceType>();
    services.AddHostedService(x => x.GetRequiredService<MyBackgroundServiceType>());
    services.AddHealthChecks().AddCheck<MyBackgroundServiceType>(typeof(MyBackgroundServiceType).Name);

一切都很好。

© www.soinside.com 2019 - 2024. All rights reserved.