2012-04-12 5 views
9

나는 ASP.NET MVC3의 소스 코드를 읽고 있어요, 나는 ControllerBase에 대한 코드의 내부에 다음 건너 온 :이 코드의 요점은 무엇입니까?

public interface IController 
{ 
    void Excecute(RequestContext requestContext); 
} 


public abstract class ControllerBase : IController 
{ 

    protected virtual void Execute(RequestContext requestContext) 
    { 
     if (requestContext == null) 
     { 
      throw new ArgumentNullException("requestContext"); 
     } 
     if (requestContext.HttpContext == null) 
     { 
      throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext"); 
     } 

     VerifyExecuteCalledOnce(); 
     Initialize(requestContext); 

     using (ScopeStorage.CreateTransientScope()) 
     { 
      ExecuteCore(); 
     } 
    } 

    void IController.Execute(RequestContext requestContext) 
    { 
     Execute(requestContext); 
    } 
} 

ControllerBase는 Execute의 구현을 제공하지만, 그것은 제공하는 뭔가가 .. IController.Execute에 대한 정의?

왜 이렇게 되었습니까? 아무런 도움이되지 않는 것 같습니다.

+0

가상'Execute'를 오버라이드하는 경우는, 명시 적으로는'IController.Execute' 여전히 기본 구현을 실행합니다 :

나는 여기에 대한 좋은 기사를 발견? – Joe

+0

@Joe No. 오버 라이딩 된 가상 Execute가 있으면 실행합니다. – Scott

+0

어쩌면 그 방법은 '공개'가 아닌 '보호 된'방법 일뿐입니다. – Joe

답변

6

이 코드를 사용하면 Execute 메서드를 재정의 할 수 있습니다.

정상적으로 구현 된 인터페이스 메서드는 public (가상 또는 추상이 아님)이므로 파생 클래스에서 재정의 할 수 없으며 기본적으로 IController 인터페이스를 통해 새 Execute 메서드를 만들 수 없습니다. 보호 된 가상 기술에 대한이 인터페이스). 명시 적으로 구현 된 인터페이스 메서드에서 호출하는 보호 된 가상 메서드를 만들면 파생 클래스가 인터페이스 구현을 위반하지 않고 Execute 메서드를 재정의 할 수 있습니다. C# Overriding Interface Methods in Subclasses

+0

그래서 본질적으로 하위 클래스에서 변경하려는 인터페이스를 통해 일부 기능을 공개하려는 경우이 패턴을 사용할 수 있습니다. –

+0

'public virtual Execute (RequestContext requestContext) '보다 왜이 디자인 패턴을 선호합니까? – Scott

+2

@Scott public virtual을 사용하면 IController 인터페이스에 대한 참조없이이 클래스 외부에서 액세스 할 수 있습니다. 공개 될거야. protected를 사용하면 IController 인터페이스에 대한 명시적인 참조가없는 한 메서드를 ControllerBase 클래스 및 그 자손 내부에서 유지합니다. 따라서 더 잘 보호되고 매우 의도적으로 액세스 할 때만 사용됩니다. – BenSwayne

2

MSDN Documentation에 따르면 명시 적 인터페이스 멤버 구현의 한 가지 목적은 "명시 적 인터페이스 멤버 구현이 클래스 또는 구조체 인스턴스를 통해 액세스 할 수 없기 때문에 인터페이스 구현이 클래스 또는 구조체의 공용 인터페이스에서 제외 될 수 있습니다. 클래스 나 구조체가 그 클래스 나 구조체의 소비자에게 관심이없는 내부 인터페이스를 구현할 때 특히 유용합니다. "

위의 내용이 정확하면 ControllerBase 유형의 변수는 Execute이 보호되어있어 호출 할 수 없습니다. 변수 유형은 IController이어야합니다. 이것은 이것이 구조물의 의도인지 확실하지 않지만, 이것이 그 이유라고 생각합니다.

관련 테스트에서 그들은 을 호출하기 전에 에 명시 적으로 ControllerBase 변수를 캐스팅합니다.

+0

예. 아마도 "외부"에서 Execute 호출을 모호하게 만드는 것은 단지 멋진 방법 일 것입니다. – Scott

+1

@ 스콧 내 생각에 이것은 책임의 분리를 시행하는 데 사용됩니다. 'ControllerBase' 레퍼런스를 가지고 있다면, 그것을 실행할 의도가 없습니다. 'IController'를 가지고 있다면, 당신은 그것을 실행하기위한 것입니다. – vhallac

1

언뜻보기에이 디자인 패턴은 아무런 도움이되지 않는 것처럼 보입니다. 그러나 ControllerBase 클래스가 나중에 변경되지 않는 변경을 수행하여 IController 인터페이스를 구현할 수있는 기회를 제공합니다. base.Execute()을 호출하는 상속 된 클래스에 의존하지 않으므로 변경 사항이 실행되도록 보장됩니다. 아마도 이것은 컨텍스트 나 보안을 관리하는 데 사용될 수 있습니까?

아마도 개발자는 인터페이스를 논리적으로 분리하여 구현할 수 있기를 좋아합니다.

관련 문제