Bug:使用拦截器的时候从容器获取对象时调用的构造方法错误
Closed this issue · 3 comments
MateralCMX commented
我有这样两个接口
public interface IInteriorService
{
void SayHello();
}
public interface IExternalService
{
void SayHello();
}
有两个类分别实现了他们
public class InteriorServiceImpl : IInteriorService
{
public void SayHello() => Console.WriteLine("Hello Interior!");
}
public class ExternalServiceImpl : IExternalService
{
private readonly IInteriorService? _service1;
public ExternalServiceImpl()
{
Console.WriteLine("ExternalServiceImpl()");
}
public ExternalServiceImpl(IInteriorService service1) : this()
{
_service1 = service1;
Console.WriteLine("ExternalServiceImpl(IParentService)");
}
public void SayHello()
{
Console.WriteLine("Hello External!");
_service1?.SayHello();
}
}
并实现了一个拦截器
public class CustomInterceptor : AbstractInterceptor
{
public override async Task Invoke(AspectContext context, AspectDelegate next) => await context.Invoke(next);
}
这是主要方法
public class Program
{
public static void Main()
{
IServiceCollection services = new ServiceCollection();
services.AddTransient<IInteriorService, InteriorServiceImpl>();
services.AddTransient<IExternalService, ExternalServiceImpl>();
services.ConfigureDynamicProxy(option =>
{
option.Interceptors.AddTyped<CustomInterceptor>();
});
IServiceProvider serviceProvider = services.BuildDynamicProxyProvider();
IExternalService service2 = serviceProvider.GetRequiredService<IExternalService>();
service2.SayHello();
}
}
期望输出为:
ExternalServiceImpl()
ExternalServiceImpl(IParentService)
Hello External!
Hello Interior!
实际输出为:
ExternalServiceImpl()
Hello External!
经过调试发现,在使用拦截器后(不论是全局方式还是Attribute方式),从容器获取接口实现类时调用的构造函数不是参数最多的构造函数(这只是表象),在该示例中,容器调用了方法ExternalServiceImpl()而非ExternalServiceImpl(IParentService)方法,我还发现调用的构造函数与代码文件中的位置有关
将类ExternalServiceImpl调整为如下代码后(交换了构造函数的位置),获得了期望输出
public class ExternalServiceImpl : IExternalService
{
private readonly IInteriorService? _service1;
public ExternalServiceImpl(IInteriorService service1) : this()
{
_service1 = service1;
Console.WriteLine("ExternalServiceImpl(IParentService)");
}
public ExternalServiceImpl()
{
Console.WriteLine("ExternalServiceImpl()");
}
public void SayHello()
{
Console.WriteLine("Hello External!");
_service1?.SayHello();
}
}
示例地址AspectCoreDemo
nivalxer commented
这个问题上是runtime的一个bug,在.net8里面被修复了
dotnet/runtime#46132
临时修复方案就是按提供的示例一样,把需要注入的构造函数放前面
liuhaoyang commented
👍🏻
MateralCMX commented
这个问题上是runtime的一个bug,在.net8里面被修复了 dotnet/runtime#46132 临时修复方案就是按提供的示例一样,把需要注入的构造函数放前面
经过验证确实是这个Bug导致的