如何在Ninject的OnActivation()中传入父对象作为参数?
你的思路完全正确!
你想用Ninject的OnActivation钩子来自动调用SubscribeAll的想法完全没问题,这正是这个扩展方法设计的初衷——用来处理那些不能放在构造函数里的实例化后初始化逻辑,尤其是像你这种因为循环引用限制,必须依赖父对象的场景。
不过你可能踩了一个容易忽略的小坑,导致代码没生效:ctx.Request.Target本身并不是父对象实例,它是ITarget类型,代表的是当前服务被注入到的目标成员(比如父对象的构造函数参数、属性),要拿到父对象的实例,你需要访问ctx.Request.Target.Object。
修正后的代码应该是这样的:
Bind<IMessageService>().To<QueuedMessageService>() .InSingletonScope() .OnActivation((ctx, svc) => { // 先做空判断,避免直接解析服务时Target为null导致异常 var parentObject = ctx.Request.Target?.Object; if (parentObject != null) { svc.SubscribeAll(parentObject); } });
另外还有几个需要注意的点:
- 这个
OnActivation逻辑只会在服务实例被激活的时候执行一次,因为你用了InSingletonScope(),所以单例的QueuedMessageService只会触发一次。如果你的父对象是多实例的,那只有第一个父对象注入时会执行SubscribeAll,后续的父对象不会触发。这种场景下,你可以换个思路,在父对象的绑定里添加OnActivation逻辑:
这样每个父对象实例化时都会调用服务的Bind<IParentType>().To<ParentImplementation>() .OnActivation((ctx, parent) => { var messageService = ctx.Kernel.Get<IMessageService>(); messageService.SubscribeAll(parent); });SubscribeAll,更贴合多实例父对象的场景。 - 如果是直接通过
kernel.Get<IMessageService>()解析服务,而不是作为依赖注入到父对象中,ctx.Request.Target会是null,所以空判断很有必要,避免空引用异常。
总的来说,你的核心思路是对的,调整一下父对象实例的获取方式,应该就能达到你想要的自动执行效果了。
内容的提问来源于stack exchange,提问作者Matthew Goulart
相关产品推荐
相关产品推荐

