我有一个InfoPath表单,我需要有条件地禁用它的OnChange事件。由于在表单加载后无法绑定事件处理程序,因此我不得不依赖一个全局计数器来指示是否应该执行OnChange事件。 在每个OnChange事件中,我在执行任何操作之前检查SuppressEventsCount == 0。 为了在执行某个函数或其他函数期间抑制事件,我只需设置SuppressEventsCount ++,并且 - 当函数退出时再次。这样做的最大问题是它不是例外。所以我有一个好主意将SuppressEvents计数器包装在一个实现iDisposable
的类中using(SuppressEvents s = new SuppressEvents()){
// OnChange events fired here are ignored
} // OnChange events enabled again
这是有效的,但它仍然不如c ++解决方案那么理想,它根本不需要使用“using”指令。
有没有办法:
答案 0 :(得分:7)
不,不。 using
是最接近RAII的(更准确地说,我们正在谈论被破坏的RAII-idiom对象之后的资源释放)。
更直接地回答您的观点:
IDisposable
(以及扩展名using
)的创建完全是因为在.NET中无法做到这一点。using
是语法糖,它被编译为try
/ finally
并且只要求对象为IDisposable
,因此您无法区分{{1}内的用法声明和它之外。答案 1 :(得分:2)
关于问题2,可以通过为代码的消费者提供不同的接口来绕过它。而不是提供实现IDisposable
的公共类,并希望它们将它包装在using
中,您可以提供一个静态方法,该方法将函数在“被抑制”的上下文中执行:
public static class EventSuppressor {
public void Suppress(Action action) {
using (var s = new SuppressActions()) {
action();
}
}
private class SuppressActions : IDisposable {
...
}
}
然后消费者可以按如下方式使用:
EventSuppressor.Suppress(() => {
// OnChange events fired here are ignored
}) // OnChange events enabled again
当然,你必须弄清楚这个设计是否合适,因为这将导致额外的函数调用,编译器生成的类和闭包等。
答案 2 :(得分:1)
回答你的两个问题:
using
子句被转换为try / finally块类型的代码,并且无论如何您无法检测到它是从这两个构造中的任何一个构造的,与外部< / LI>
醇>
答案 3 :(得分:0)
如果你可以从C#转移到C ++ .NET(如果使用clr:safe编译,仍然是100%.NET),那么你可以使用msclr :: auto_handle,它就像一个智能指针,如auto_ptr等... < / p>
在IL的场景背后真正做的是一堆try / fault命令,但这对于开发人员和用户来说都是完全不可见的。整个过程简直就是IMO。