2

我想要一个 EventWaitHandle 对象(例如 ManualResetEvent),它只能从一个地方设置/重置,但可以从多个地方等待(使用 WaitOne())。换句话说,我希望只有一个类可以设置/重置它,而所有其他类都可以调用 WaitOne() 。这有点像常规的“只读”属性:

private string MyReadOnlyText {get; private set;}

仅适用于 ManualResetEvent 中的特定方法。但不是:

private ManualResetEvent MyEvent {get; private set;}

当然,这是行不通的,因为虽然只有所有者类可以实例化该属性,但任何其他外部对象都可以使用 MyEvent.Set/MyEvent.Reset() 来更改它。

这样的事情甚至可能吗?这样做的目的是防止应用程序中的任意对象操纵等待句柄状态,并确保这可以仅从一个地方完成。

4

1 回答 1

2

在某种程度上,这似乎是可以通过约定解决的问题,即只需规定句柄应被消费者视为“只读”。通过源代码进行简单的 grep 应该有助于确保防止不法分子。

如果仅将对象公开为WaitHandle. WaitHandle实例没有Set()方法,因此有助于提醒调用者不要乱用它。

当然,调用者仍然可以将它转换为它的实际类型,并且WaitHandle仍然允许操作的静态方法。因此,这并不是 100% 的保证。但这会有所帮助(并在您进行代码审核时为 grep 提供更多独特的模式)。

最后,评论中提到的“包装器”方法也可以工作。这是最健壮的,并且对于任何类型的“限制对除所有者对象之外的成员的访问”都是一种相对常见的模式。

如果调用者与特权代码位于不同的程序集中,那么最简单的方法是使隐藏的东西“内部”和公共的东西“公共”。如果它们在同一个程序集中,那么如果你可以把具有特权代码的同一类中的隐藏成员,那么它们当然可以只是该类的私有。

但通常,您希望将特殊可访问性对象封装为一个单独的类,同时仍授予对一个特定类的特权访问权限并限制其他所有人的访问权限。在这种情况下,您可以使用嵌套类来实现这种分离,外部类包含特权代码,而嵌套类包含隐藏代码。

这种方法的一个版本使用基类/子类设计,其中基类具有公共成员,子类具有隐藏代码:

class A
{
    public class B
    {
        protected ManualResetEvent _event = new ManualResetEvent(false);

        public void Wait() { _event.Wait(); }
    }

    private class C : B
    {
        public void Set() { _event.Set(); }
    }

    public B GetAnInstanceofB() { return new C(); }

    private void DoSomethingWithB(B b) { ((C)b).Set(); }
}

现在调用者可以B.Wait()在返回的实例上调用 ,但他们不能转换为类型C来访问该Set()方法。但请注意,类中的代码A是允许的(因为它可以将类型强制转换为C)。

请注意,类B本身不需要嵌套。只是C

这个主题的另一个变体是声明一个只包含公共方法的接口,然后有一个接口的实现者。同样,实现类将嵌套为特权代码私有,而接口可以嵌套或不嵌套。

最后请注意,所有这些都是代码可靠性和维护的问题。当然,代码总是可以使用反射来检查和访问它想要的任何类型的任何部分。

归根结底,您必须考虑代码的受众。如果是一个小团队,并且代码完全独立于一个项目,那么只告诉每个人“你可以等待这个,但不要搞砸这个事件”可能就足够了。在更大的环境中,可能有几个团队一起从事多个相关项目,但基本上仍然是一个独立的单元,使用WaitHandle可能就足够了。如果您正在编写一个打算广泛使用的库,那么封装和私有成员和类是一个很好的工具。:)

于 2014-10-24T00:14:14.607 回答