【问题标题】:Intercept creation of instances in Ninject在 Ninject 中拦截实例的创建
【发布时间】:2015-01-14 18:10:01
【问题描述】:

我希望拦截实现特定接口或具有特定属性的实例的创建。我可以做一些与拦截扩展类似的事情,但这似乎只做方法和属性拦截。

这是我如何拦截方法和属性调用,但它不拦截构造函数调用:

_kernel.Bind<IInterceptor>().To<LogInterceptor>().InSingletonScope();
_kernel.Intercept(x =>
{
    if (x.Plan.Type.GetInterface(typeof(ITriggerLoggingInterception).FullName) != null)
    {
        return true;
    }

    return false;
}).With<LogInterceptor>();

【问题讨论】:

  • 我一直在寻找,但仍然找不到方法,这通常表明我正在尝试做一些我不应该做的事情。
  • 拦截ctor想达到什么目的?它需要有多灵活?这些可能是替代方案:.ToProvider&lt;TProvider&gt;() 绑定或.OnActivation() 绑定扩展。
  • 我正在开发基于插件的 Caliburn Micro 应用程序。有一个 eventAggregator 组件,我想让开发人员轻松利用它。通常,为了使用这个组件,您必须注入一个 eventAggregator 并在其上调用 Subcribe(),然后实现 IHandle 接口,该接口告诉 eventAggregator 调用这些事件处理程序。为方便起见,我想拦截 post 构造函数调用,如果该类实现了 IHandle 接口,则为其调用 Subscribe()。这会很好,因为我可以看到开发人员忘记这样做并浪费时间跟踪它。
  • 好的。谁/谁/何时创建绑定?我们使用了事件代理。并且向它注册发布者/订阅者是通过扩展 ninject 的 OnActivation 的自定义 RegisterBrokeredEvents() 扩展完成的。这称为 post-ctor。

标签: c# ninject ninject-interception


【解决方案1】:

正如您自己发现的那样,最接近于对每个绑定进行实例化(无需更改绑定)的方法是 IActivationStrategy

例如(示例取自here:

public class StartableStrategy : ActivationStrategy
{
  public override void Activate(IContext context, InstanceReference reference)
  {
    reference.IfInstanceIs<IStartable>(x => x.Start());
  }

  public override void Deactivate(IContext context, InstanceReference reference)
  {
    reference.IfInstanceIs<IStartable>(x => x.Stop());
  }
}

通过以下方式添加到ninject内核中:

kernel.Components.Add<IActivationStrategy, StartableActivationStrategy>();

替代 - 绑定语法糖

让我更详细地了解我在 cmets 中提到的 OnActivation() 扩展:

    public static IBindingOnSyntax<T> RegisterEvents<T>(this IBindingOnSyntax<T> binding)
    {
        // todo check whether <T> implements the IHandle<> interface, if not throw exception
        return binding
            .OnActivation((ctx, instance) => ctx.Kernel.Get<EventAggregator>().Subscribe(instance));
    }

您将手动将其用于绑定:

kernel.Bind<FooViewModel>().ToSelf()
      .RegisterEvents()
      .InSingletonScope();

(不需要InSingletonScope() - 这只是为了表明您可以像以前一样使用其他绑定扩展/功能)。

现在我认为您想使用它而不是“按惯例”。如果您按照约定 (ninject.extensions.conventions) 创建绑定,则可以使用 IBindingGenerator 相应地创建绑定(无论是否调用 RegisterEvents)。如果没有,那就更棘手了。我会说你必须扩展 ninject 的管道。

【讨论】:

  • 绑定在两个地方创建。该应用程序在启动时会绑定记录器工厂等基本内容,然后循环通过插件并让每个插件都有机会添加自己的绑定。
  • 所以我想问题是让他们在课堂或绑定中连接它是否更好。仍然不是他们的目标,但非常好。谢谢。
  • 酷,不知道那个!您自己创建一个答案并接受它怎么样?我认为这可能是您想要实现的更好的方法。 ninject wiki 中也有一个条目here
  • 如果您只是编辑并将其放入,那么答案将涵盖所有可能性。不幸的是,它不适合我,因为我也使用拦截。城堡生成的代理没有实现与具体类型相同的接口,所以 EventAggregator 只是忽略它。即使有肮脏的黑客攻击,也无法获得底层代理的目标。不能将 IHandle 放在接口上,因为并非所有实现都可能需要订阅。我认为开发人员只需要自己订阅事件!
  • @stom 取决于绑定的范围。对于默认值 (InTransientScope),答案是从不。对于 (InSingletonScope),它是在处置内核时。对于其他人来说,这是范围结束的时间 - 在某些情况下,这些可能会延迟,因为根据用例,这只能由定期运行的后台作业检测到,该作业检查 WeakReference 是否到范围 IsAlive。如果您实现自己的范围,则可以让范围对象实现 INotifyWhenDisposed 以实现确定性行为(它是一个 Ninject 接口)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多