如何解决Ninject 4.0.0-beta-0134 抛出“在两个服务的构造函数之间检测到循环依赖”
今天我将我们的 Ninject 依赖从 3.3.4 更新到 4.0.0-beta-0134,但现在它在装饰器模式中抛出了一个循环依赖异常:
`未处理的异常:Ninject.ActivationException:使用从 Program+IService 到 Program+Service 的条件绑定激活 Program+IService 时出错 在两个服务的构造函数之间检测到循环依赖。
激活路径: 2) 将依赖 Program+IService 注入到 Program+ServiceDecorator 类型的构造函数的参数服务中
- 请求 Program+IService
建议:
- 确保您没有在服务的任何实现上声明 Program+IService 的依赖项。
- 考虑将这些服务合并为一个服务以消除循环。
- 使用属性注入代替构造函数注入,并实现IInitializable 如果您需要在注入属性值后运行初始化逻辑。 `
这是示例代码:
public static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Load(new IocConfig());
kernel.Get<IService>().Serve();
}
internal interface IService
{
void Serve();
}
public class Service : IService
{
public void Serve() { }
}
public class ServiceDecorator : IService
{
private readonly IService _service;
public ServiceDecorator(IService service) => _service = service;
public void Serve() => _service.Serve();
}
public class IocConfig : NinjectModule
{
public override void Load()
{
Bind<IService>().To<Service>().WhenInjectedInto<ServiceDecorator>().InSingletonScope();
Bind<IService>().To<ServiceDecorator>().InSingletonScope();
}
}
它似乎不喜欢在 NinjectModule 中使用 WhenInjectedInto
。我发现了其他类似的问题,但没有发现 WhenInjectedInto
不起作用。
解决此问题的一种方法是将服务参数类型从 IService
更改为 Service
,但这会破坏使用装饰器的大部分原因。
你们中有人知道其他解决方案/变通方法吗?
解决方法
不清楚您打算如何使用此示例中的装饰器,但一种可能性是对装饰器应用一个新接口,该接口又继承自 IService
。
public interface IServiceDecorator : IService { }
public interface IService
{
void Serve();
}
public class Service : IService
{
public void Serve() { }
}
public class ServiceDecorator : IServiceDecorator
{
private readonly IService _service;
public ServiceDecorator(IService service) => _service = service;
public void Serve() => _service.Serve();
}
public class IocConfig : NinjectModule
{
public override void Load()
{
Bind<IService>().To<Service>().InSingletonScope();
Bind<IService>().To<Service>().WhenInjectedInto<ServiceDecorator>().InSingletonScope();
Bind<IServiceDecorator>().To<ServiceDecorator>().InSingletonScope();
}
}
,
再次通过后,似乎问题实际上是由使用 .WhenInjectedInto<ServiceDecorator>
引起的,因为绑定之间没有区别。
另一种方法是简单地使用 Bind<IService>().To<Service>().InSingletonScope();
,然后将 BindingConfiguration.Condition
添加到您的装饰器来处理 Get<ServiceDecorator>()
用例:
public static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Load(new IocConfig());
kernel.Get<IService>().Serve();
kernel.Get<ServiceDecorator>().Serve();
}
public interface IService
{
void Serve();
}
public class Service : IService
{
public void Serve() { Console.WriteLine("service"); }
}
public class ServiceDecorator : IService
{
private readonly IService _service;
public ServiceDecorator(IService service) => _service = service;
public void Serve() { Console.WriteLine("decorator"); _service.Serve(); }
}
public class IocConfig : NinjectModule
{
public override void Load()
{
Bind<IService>().To<Service>().InSingletonScope();
Bind<IService>().To<ServiceDecorator>().InSingletonScope().BindingConfiguration.Condition =
(Ninject.Activation.IRequest request) =>
request.Service == typeof(ServiceDecorator);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。