kirov-opensource / NAutowired

ASP.NET CORE Field Injection Implement
MIT License
77 stars 16 forks source link

通过构造函数注入的情况,注入进来的类型内部使用Autowrid标记的属性或字段不生效 #10

Open jrt324 opened 4 years ago

jrt324 commented 4 years ago
[Service]
public class ServiceA{
  [Autowired]
  private Test test;

 public void TestMethod(){
   //此时 test是null
 }
}

[ApiController]
public class AccountController{
  private readonly ServiceA _serviceA;
  public AccountController(ServiceA  serviceA){
    _serviceA = serviceA;
  }

 public void TestAction(){
  _serviceA.TestMethod();
}

}
FatTigerWang commented 4 years ago

请问Test类使用[Service] Attribute 标记了吗

jrt324 commented 4 years ago

Test类是通过其他方式注册到容器的,services.AddSingleton< Test >();

FatTigerWang commented 4 years ago
[ApiController]
public class AccountController{
  //此处需要使用Autowired注入
  [Autowired]
  private readonly ServiceA _serviceA;
  public AccountController(ServiceA  serviceA){
    _serviceA = serviceA;
  }

 public void TestAction(){
  _serviceA.TestMethod();
}

这是由于我们只查找了具有Autowired特性标记的依赖进行还原。 下个版本考虑支持对构造函数注入的依赖进行还原。

jrt324 commented 4 years ago

主要考虑历史代码有大量的构造函数注入的情况,所有做到兼容还是有必要的

JamesYing commented 3 years ago

@FatTigerWang 刚看了下代码,Service是通过Castle方式批量注入的

 services.Add(new ServiceDescriptor(aInterface, serviceProvider =>
                                {
                                    CastleInterceptor castleInterceptor = new CastleInterceptor(serviceProvider);

                                    return _generator.CreateInterfaceProxyWithTarget(aInterface, serviceProvider.GetService(aType), castleInterceptor);
                                }, aMap.Value));

这种方式在Service层好像就无法用 [Autowired]了

FatTigerWang commented 3 years ago

这是个动态代理,它实际上创建的是代理对象。代理对象加入到容器中,是无法还原出本来的对象的。 你可以typeof一下你得到的service实例,应当是个proxy class。 @JamesYing

sampsonye commented 2 years ago

Hello 这个问题有被解决嘛

看起来并不可行,一旦构造函数注入和属性注入并用,构造函数注入的Service是无法应用属性注入的
例如:
class ServiceA{
    [Autoired]
    public ILogger<ServiceA> Logger{get;set;}
}

class ServiceB{
    public ServiceB(ServiceA a){
     //...
    }
}

构造ServiceB后,ServiceA中的Logger并没有应用属性注入

FatTigerWang commented 2 years ago

Hello 这个问题有被解决嘛

看起来并不可行,一旦构造函数注入和属性注入并用,构造函数注入的Service是无法应用属性注入的
例如:
class ServiceA{
    [Autoired]
    public ILogger<ServiceA> Logger{get;set;}
}

class ServiceB{
    public ServiceB(ServiceA a){
     //...
    }
}

构造ServiceB后,ServiceA中的Logger并没有应用属性注入

因为在实例化类调用构造函数时,NAutowired一无所知,它是在类已经被实例化完成后再进行属性赋值的, 因此在构造函数中使用带有Autowired Attribute的字段是无法起作用的。也许引入类似Castle之类的动态代理能够解决。

softworm commented 1 year ago

因为在实例化类调用构造函数时,NAutowired一无所知,它是在类已经被实例化完成后再进行属性赋值的, 因此在构造函数中使用带有Autowired Attribute的字段是无法起作用的。也许引入类似Castle之类的动态代理能够解决。

或许可以考虑反射获取构造函数及参数,再逐个检查注入对象型参数的属性。但使用构造函数注入依赖时,其形参通常是接口类型或基类类型,这时处理起来也非常棘手。因为单纯通过反射根本无法获取实参,况且也无法得知构造参数与字段的对应关系。

如果引入动态代理,将构造函数代理并逐个检查注入实参,这样理论上确实可行。:smile: