Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

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

Open
jrt324 opened this issue Sep 23, 2020 · 9 comments
Labels

Comments

@jrt324
Copy link

jrt324 commented Sep 23, 2020

[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
Copy link
Member

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

@jrt324
Copy link
Author

jrt324 commented Sep 24, 2020

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

@FatTigerWang
Copy link
Member

FatTigerWang commented Sep 24, 2020

[ApiController]
public class AccountController{
  //此处需要使用Autowired注入
  [Autowired]
  private readonly ServiceA _serviceA;
  public AccountController(ServiceA  serviceA){
    _serviceA = serviceA;
  }
  
 public void TestAction(){
  _serviceA.TestMethod();
}

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

@FatTigerWang FatTigerWang added this to the 2.2.0 milestone Sep 24, 2020
@FatTigerWang FatTigerWang added the enhancement New feature or request label Sep 24, 2020
@jrt324
Copy link
Author

jrt324 commented Sep 24, 2020

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

@JamesYing
Copy link

@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
Copy link
Member

FatTigerWang commented Dec 2, 2020

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

@FatTigerWang FatTigerWang added wontfix This will not be worked on and removed enhancement New feature or request labels Dec 2, 2020
@FatTigerWang FatTigerWang removed this from the 3.0.0 milestone Dec 2, 2020
@sampsonye
Copy link

Hello 这个问题有被解决嘛

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

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

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

@FatTigerWang
Copy link
Member

FatTigerWang commented Aug 31, 2022

Hello 这个问题有被解决嘛

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

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

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

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

@FatTigerWang FatTigerWang added next and removed wontfix This will not be worked on labels Aug 31, 2022
@softworm
Copy link
Contributor

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

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

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants