2010-01-15 10 views
1

신용 카드 클래스를 사용하는 주문 (집계 클래스)을 속성으로 가정합니다. 주문 상태에 따라 신용 카드 클래스 속성의 액세스 한정자를 변경하려고합니다. 예를 들어, Order state = Order.NewOrder 인 경우 신용 상태 정보를 수정할 수 있도록 허용하지만 Order state = Order.CompletedOrder 인 경우 신용 카드 속성을 설정할 수 없습니다.상태에 따라 C# 액세스 한정자

컴파일 시간과 런타임에서 확인할 수 있기를 원합니다.

내가 생각한 유일한 해결책은 동일한 상위 클래스에서 상속하는 2 개의 클래스를 만드는 것이 었습니다. 하나는 속성을 다른 하나는 설정할 수 없지만 어떤 속성은 설정 가능하고 다른 속성은 설정할 필요가있는 경우 매우 빠르게 털이 있습니다.

모든 아이디어를 매우 높이 평가합니다.

+1

어떻게하면이 작업에 대한 컴파일 타임 솔루션을 구상하겠습니까? – jason

+0

그는 자신의 VS 확장을 쓸 것입니다. – ChaosPandion

+0

그래, 2 정적 클래스를 만드는 방법은 컴파일 시간을 확인하는 방법입니다. 그러나 나는 여전히 하나의 클래스를 가지며 런타임 'OperationNotAllowed'종류의 오류를 던질 것입니다. 하나의 유형에 대해 코드를 복제/동기화/유지하는 두 가지 클래스가 있습니다. – Gishu

답변

2

이 문제를 해결하는 또 다른 방법은 보호 프록시로 '디자인 패턴'pg.208-209입니다.

"Proxy pattern"은 다른 개체에 대한 액세스를 제어하기위한 대리 또는 자리 표시자를 제공합니다. " 실제 객체 대신 보호 프록시 버전의 객체를 넣고 보호 프록시의 액세스 논리는 읽기 전용 데이터를 반환하지만 쓰기 시도는 검사합니다.

+0

당신이 컴파일 타임 검사 대 런타임 검사를 원하는 이유는 비즈니스 객체로 작업하는 개발자가 집합을 수행하기를 원하지 않기 때문입니다. 예를 들어 Order.CreditCard.Number = ... 그리고 ' 예외가 Throw되었을 때. 개체는 항상 개발자가 IsChangeAllowed() 등을 실행할 필요가 없도록 디자인되어야합니다. – traderde

+0

"개발자는 IsChangeAllowed()를 실행하기 위해 개발자가 알 필요가 없도록 항상 디자인되어야합니다. 몹시 떠들어 대다. 나는 개발자가 수표를 써야한다는 것을 암시하는 것을 의미하지는 않았다. 나는 단지 당신의 문제를 이해하려고 노력하고있다. –

+0

이 솔루션의 문제점은 IsWritable = false이고 사용자가 올바르게 설정되지 않은 이유를 직관적으로 알 수없는 경우 set가 실행된다는 것입니다. – traderde

3

몇 가지 인터페이스가있는 신용 카드 개체를 나타냅니다. 하나는 세터와 다른 게터를 가질 것입니다. Order 클래스의 CreditCard 속성은 getter 인터페이스 일뿐입니다.

class CreditCardBase : ICreditCard 
{ 
    string Name { get; } 
} 

interface IWritableCreditCard : ICreditCard 
{ 
    string Name { get; set; } 
} 

class WritableCreditCard : CreditCardBase, IWritableCreditCard {} 

class Order 
{ 
    private ICreditCard _card = new WritableCreditCard(); //initially... 
    public ICreditCard Card { get {return _card; } } 

    void OnComplete(...) { _card = new CreditCardBase(copy from _card); } 
} 

런타임에서 캐스트 "카드"세터 인터페이스의 속성은 카드의 속성을 수정할 수 있습니다. 순서 상태가 이제 읽기 전용 상태 인 경우, CreditCard를 구현하는 객체는 getter 만 구현 한 구현으로 스왑됩니다.

나는 컴파일 타임에 어떻게 구별 할 수 있는지 보지 못했지만 최소한 정상적인 동작은 안전한 "getter only"호출이 될 것이고 수정 코드는 a) 추악하고 감지하기 쉽고 b) 잘못된 시간에 실행되면 null을 반환하거나 throw합니다.

+0

이것은 getters 만있는 클래스와 모든 backing 필드를 읽기 전용으로 사용하여 속성을 인스턴스화 할 때만 설정할 수 있다는 것을 제외하고는 비슷한 생각입니다. 변경이 필요한 경우 새 인스턴스를 만들고 기존의 모든 속성 + 변경 사항을 새 인스턴스에 복사합니다. – traderde

+0

@Daver : 예제를'WritableCreditCard' 클래스를 어떻게 표현하는지 업데이트 할 수 있다고 가정하지 않습니까? 나는'new'가 상속 된 속성'get'에 적용될 것이기 때문에 당신이 그것을 어떻게 할 것인지 생각할 수 없습니다, 그러나'set'을 "new"로 만들지는 않습니다. 액터를 오버라이드 (override) 할 때'virtual'을 만들 수도 있습니다. – Codesleuth

관련 문제