如何使用 Ninject 设置可选方法拦截?
假设我有一个类,我有时想*(但现在总是)拦截一些(但不是全部)方法。按照我的理解,这可以通过我的 Ninject 模块(在更高级别的代码中)中的 InterceptAround()
来完成,或者使用这些方法上的 InterceptAttribute 派生属性来完成(在实施水平)。
我不太喜欢第一种方法,因为它需要消费者了解细节,会有很多类和很多方法。但我也不喜欢第二种方式,因为我不知道如何禁用(或者更确切地说,不启用)拦截,因为属性与代码融合在一起。
有一些已知的方法可以解决这个问题吗?
*:在应用程序的生命周期内。
Suppose I have a class in which I want to sometimes* (but now always) intercept some (but not all) methods. The way I understand it, this can be done either with, say, InterceptAround()
in my Ninject module (in the higher-level code), or with an InterceptAttribute-derived attribute on those methods (at the implementation level).
I don't really like the first way of doing it, because it requires the consumer to know the details, there'll be many classes with many methods. But I don't like the second way either, since I don't see how to disable (or, rather, not to enable) the interception, as the attribute is fused with the code.
Is there some known approach to solve this problem?
*: for the lifetime of the application.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
听起来好像您指的是普通的动态拦截器,这就是 Ninject Interception 扩展默认的工作方式。
下面是一个条件拦截的示例:
您可以将其直接绑定到单个类,如下所示:
如果您想动态拦截单个类,这几乎就是您所要做的全部事情。
内核扩展看起来很有前途,因为它们允许您将条件直接写入声明中:
但是,如果您尝试根据方法做出决策,这并不是特别有用正在执行,因为这只能让您访问绑定上下文,而不是调用。主要是,此扩展的存在是为了让您可以选择在运行时拦截哪些类或服务(而不是方法)。
最好坚持绑定语法,并将运行或不运行逻辑直接写入拦截器,如第一个示例所示。
需要注意的一件重要事情是,动态拦截器实际上会为它绑定到的任何类上的每个(公共/虚拟)方法运行,这可能非常低效。不幸的是,Ninject Interception 扩展必须采用最低公分母方法,因为它旨在支持多个代理库。如果直接使用Castle,可以 使用代理生成钩子和拦截器选择器进行细粒度控制,这实际上是推荐的方法。据我从 Ninject-DP2 源代码来看,Ninject 扩展不支持这一点。
就我个人而言,正是由于这个原因,我从未在 Ninject Interception 扩展方面取得过很大的成功,并且倾向于直接使用 Castle DP2。但是,如果您正在小规模地执行此操作并且不编写性能敏感的应用程序,那么您应该可以编写动态拦截器。
It sounds as though you are referring to an ordinary dynamic interceptor, which is how the Ninject Interception extension works by default.
Here's an example of a conditional interception:
You bind it directly to a single class like so:
And that's pretty much all you have to do if you want to dynamically intercept a single class.
The kernel extensions look promising because they let you write conditions directly into the declaration:
However, this isn't particularly useful if you're trying to make decisions based on the method being executed, because this only gives you access to the binding context, and not the invocation. Mainly, this extension exists so that you can choose which classes or services (as opposed to methods) to intercept at runtime.
Better to stick to the binding syntax, and write the run-or-don't-run logic directly into the interceptor, as illustrated in the first example.
One important thing to note is that a dynamic interceptor will actually run for every (public / virtual) method on whichever class it is bound to, which can be very inefficient. Unfortunately, the Ninject Interception extension has to take a lowest-common-denominator approach because it is designed to support multiple proxy libraries. If you use Castle directly, you can use proxy generation hooks and interceptor selectors for fine-grained control, which is actually the recommended approach. As far as I can tell from the Ninject-DP2 source code, this is not supported with the Ninject extension.
Personally, I've never had a lot of success with the Ninject Interception extension for exactly this reason, and tend to stick to using Castle DP2 directly. However, if you're doing this on a small scale and aren't writing a performance-sensitive app, you should be fine writing dynamic interceptors.