2014-10-23 9 views
2

하나의 장소에서 설정/재설정 할 수 있지만 여러 장소에서 WaitOne()을 기다릴 수있는 EventWaitHandle 객체 (예 : ManualResetEvent)를 갖고 싶습니다. 다르게 말해서, 다른 모든 클래스가 WaitOne()을 호출 할 수 있도록 설정/재설정 할 수있는 클래스를 하나만 갖고 싶습니다. 보통의 "읽기 전용"속성과 같습니다.EventWaitHandle의 설정/재설정을 제한 할 수 있습니까?

ManualResetEvent의 특정 메소드에만 해당됩니다. 그러나이 아닌 : 물론

private ManualResetEvent MyEvent {get; private set;} 

,이) (단 소유자 클래스는이 속성을 인스턴스화 할 수 있지만, 다른 외부 물체가 MyEvent.Set/MyEvent.Reset으로 변경 할 수 있습니다, 때문에 작동하지 않습니다.

이렇게해도 될까요? 이 기능의 목적은 응용 프로그램의 임의 개체가 대기 핸들 상태를 조작하지 못하도록하고 단일 위치에서이 작업을 수행 할 수 있는지 확인하는 것입니다.

+1

원하는 속성 (인스턴스 작성자 만 설정/재설정 할 수 있음)이있는 사용자 정의 클래스에서 사용중인 모든 기본 프리미티브를 래핑 할 수 없습니까? –

답변

2

어느 정도까지는, 이는 관례에 의해 해결 될 수있는 것처럼 보이며, 즉, 소비자가 핸들을 "읽기 전용"으로 간주해야한다고 규정합니다. 소스 코드를 통해 간단한 grep을 사용하면 악의적 인 사람을 막을 수 있습니다.

개체를 WaitHandle으로 만 공개하는 경우 "실제 전용"이벤트의 개념이 제한적으로 지원됩니다. WaitHandle 인스턴스에는 Set() 메서드가 없으므로 호출자가이를 방해하지 않도록 상기시키는 데 도움이됩니다.

호출자는 여전히 실제 유형으로 캐스팅 할 수 있으며 여전히 조작을 허용하는 WaitHandle에는 정적 메서드가 있습니다. 따라서 100 % 보장은 아닙니다. 그러나 도움이 될 것입니다 (그리고 코드 감사를 할 때 grep에 더 독특한 패턴을 제공합니다).

마지막으로 주석에 언급 된 "래퍼"접근법도 사용할 수 있습니다. 이것은 가장 강력하고 "소유자 객체를 제외한 구성원에 대한 액세스를 제한"하는 이런 종류의 모든 종류의 비교적 일반적인 패턴입니다.

호출자가 권한있는 코드와 다른 어셈블리에있는 경우 숨겨진 항목을 "내부"와 공용 항목을 "공개"로 설정하는 것이 가장 쉬운 방법입니다. 동일한 어셈블리에 있으면 숨겨진 멤버를 권한이 부여 된 코드와 같은 클래스에 넣을 수 있습니다. 그런 다음 해당 클래스에 전용으로 사용할 수 있습니다.

그래도 특수 액세스 가능 개체를 별도의 클래스로 캡슐화하고 특정 클래스에 대한 권한있는 액세스 및 다른 모든 사용자에 의한 액세스 제한이 경우 중첩 클래스를 사용하여 권한있는 코드가 포함 된 외부 클래스와 숨겨진 코드가 포함 된 중첩 클래스를 구분할 수 있습니다.

이 방법의 한 버전은 기본 클래스는 public 멤버와 하위 클래스가 숨겨진 코드가있는 기본/하위 클래스 디자인, 사용

:

지금
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을 사용하는 것으로 충분할 수 있습니다. 폭넓게 사용하려는 라이브러리를 작성하는 경우 캡슐화 및 비공개 멤버 및 클래스는 훌륭한 도구입니다. :)

+0

위대한 답변, 감사합니다! – matori82