2014-09-18 2 views
5

다음과 같이 정의 된 클래스가 있다고 가정 해보십시오.C# 참고 자료; 회원 유지하기

public class SomeClass 
{ 
    public Manager m { get; protected set; } 
    public SpecialData data { get; protected set; } 

    //More methods and member code here... 
} 

어떻게 든 SpecialData 멤버에 대한 참조를 변경할 수 있도록 관리자 클래스가 필요합니다. C++에서 이중 포인터 또는 친구 클래스를 사용하여이 작업을 수행 할 수 있지만 그 옵션은 C#에서는 사용할 수 없습니다. 슬프게도. SpecialData를 외부 사용자로부터 보호하도록 설정하는 방법은 무엇입니까? 내부 키워드로이 작업을 수행 할 수 있지만 믿을 수 없을만큼 안전하거나 깨끗하지는 않습니다 ...

도움을 주시면 대단히 감사하겠습니다.

+2

'내부'가 안전하지 않거나 부정하다고 생각하는 이유를 설명해 주시겠습니까? 그것이 일반적으로 그렇게 의미가 있습니까, 아니면 당신이 당신의 특정 디자인에 적합하지 않다고 말하고 있습니까? 나는 이것이 완벽한 솔루션이라고 말할 것입니다.하지만 진실은 처음에 왜 이것을하고 싶은지 잘 모르겠다는 말을 들었습니다. – decPL

답변

4

관리자 클래스는 멤버를 만들고, SomeClass과 동일한 어셈블리의 일부입니다 internal은 세터에 액세스하기 위해 동일한 어셈블리의 클래스 것이 가능하게 할 경우

public SpecialData data { get; protected internal set; } 

이에 friend을 사용하는 것과 비슷 C++, "우정"이 같은 어셈블리의 모든 멤버에게 확장된다는 점을 제외하고는.

관리자가 다른 패키지의 일부인 경우 어셈블리에 InternalsVisibleTo 특성을 사용할 수 있습니다. 그러나이 경우 권한이없는 코드에서 세터에 대한 액세스를 시도하지 않으려면 우정을 확장 할 어셈블리에 서명해야합니다.

+0

내부 키워드에 대해 언급했습니다. 나는 그것이 선택인지 알지만, 좋은 것인가? 누군가 디자인상의하자가 될지 모른다는 걱정이 들었습니다. 그렇지 않다면 이것은 분명히 효과가있을 것입니다. 이것은 큰 프로젝트이므로이 둘을 결합하면 막대한 문제가 될 수 있습니다. – guitar80

+0

@ user3812869 예, '내부'는 좋은 옵션입니다. 내부 표현에 대한 지식을 공유하는 관련 클래스 패키지를 디자인 할 때 이와 같은 상황을 위해 설계되었습니다. .NET은 라이브러리 외부에서이 지식을 유출하지 않도록 예방 조치를 취합니다. 아마도 어셈블리를 수정할 수있는 사람으로부터 코드를 보호 할 수있는 방법은 없습니다. – dasblinkenlight

+0

그런 경우에 나는 꼬임을 해결하려고 노력할 것입니다. 디자인은 저에게 약간 이상하게 보입니다. 실제로는 StateManager와 Sprite가 게임 객체에 포함되어 있습니다. StateManager에는 상태가 포함됩니다. 이 상태는 Sprite 필드를 편집해야합니다. – guitar80

1

SomeClass을 상속이의 종류를 보이는 클래스 만들기 : 보호

internal class SomeClassDecorator : SomeClass 
{ 
    public void SetSpecialData(SpecialData value) 
    { 
     data = value; 
    } 
} 

이 클래스의 파생 상품을 사용할 수, 그리고 SomeClass가 밀봉되지 않기 때문에, 당신은 그것에서 파생 할 간단하게 할 수 있음을 의미를 네가 필요한 건 뭐든간에. 그런 다음 SomeClass 대신이 장식자를 사용할 수 있습니다. 또한 필요한만큼 데코레이터를 사용할 수 있으며 각각은 특별 SpecialData을 처리합니다.

1

정확하지 않을 수도 있지만 internal 키워드는 here으로 표시되어 동일한 어셈블리 내에서 액세스를 제어 할 수 있습니다. C++의 friend 키워드와 비슷한 목적으로 보입니다.

1

internal 속성을 만들 수 있습니다. 그러면 속성이 동일한 어셈블리 내에서만 표시됩니다. 선택적으로 InternalsVisibleToAttribute을 사용하여 해당 어셈블리에 대한 특정 어셈블리 액세스를 허용 할 수 있습니다.

또 다른 접근법은 그 속성 숨기는 interface의 사용이다

public interface ISomeClass 
{ 
    Manager m { get; } 
    SpecialData data { get; set; } 
} 

public class SomeClass : ISomeClass 
{ 
    public Manager m { get; protected set; } 
    SpecialData ISomeClass.data { get; set; } 

    //More methods and member code here... 
} 

이와를 data 인터페이스 참조에서만 볼 수있다.

그래서이 작동하지 않습니다

SomeClass c = new SomeClass(); 
c.data; 

하지만이 작업을 수행합니다

ISomeClass c = new SomeClass(); 
c.data; 
3

게다가, Manager 클래스에 RequestChangeSpecialData 이벤트 같은 것을 이벤트를 만드는 방법에 대해. Manager이 이벤트를 실행하고 SomeClassSpecialData 인스턴스를 변경합니다.검증되지 않은

public class SomeClass 
{ 
    private Manager _m; 

    public Manager M 
    { 
     get { return _m} 
     set 
     { 
      // register/unregister event on property assignment 
      if(_m != null) 
       _m.RequestChangeSpecialData -= RequestChangeSpecialData; 

      _m = value; 

      if(_m != null) 
       _m.RequestChangeSpecialData += RequestChangeSpecialData; 

     } 
    } 

    public SpecialData Data { get; private set; } 

    private void RequestChangeSpecialData(object sender, ChangeSpecialDataEventArgs e) 
    { 
     // set the new reference 
     Data = e.SpecialData; 
    } 

} 

public class Manager 
{ 
    public void DoSomething() 
    { 
     // the manager class wants to do something, and wants to change the SpecialData instance.., so it fires the event RequestChangeSpecialData 


     SpecialData data = new SpecialData(); 

     // if the event is bound. 
     if(RequestChangeSpecialData != null) 
      RequestChangeSpecialData(this, new ChangeSpecialDataEventArgs(data)); 
    } 

    public event EventHandler<ChangeSpecialDataEventArgs> RequestChangeSpecialData; 
} 

public class ChangeSpecialDataEventArgs : EventArgs 
{ 
    public SpecialData Data {get; private set; } 

    public ChangeSpecialDataEventArgs(SpecialData Data) 
    { 
     Data = data; 
    } 
} 

는 이제 ManagerSpecialData 속성을 변경 할 수 있습니다 (메모장에 썼다). 이 방법으로 관리자는 SomeClass/인터페이스 또는 어셈블리에 종속되지 않습니다.

+0

님이 이벤트 옵션을 올릴 예정입니다. –