2012-04-12 30 views
9

Sto leggendo il codice sorgente di ASP.NET MVC3, e mi sono imbattuto nel seguente all'interno del codice per ControllerBase:Qual è il punto di questo codice?

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 fornisce un'implementazione di Execute, ma poi ha qualcosa che fornisce una definizione per .. IController.Execute?

Perché è fatto e cosa ottiene? Sembra che non serva a nulla.

+0

Se si escludeva il virtuale 'Execute', sarebbe l'esplicito' IController.Execute' ancora eseguire l'implementazione di base? – Joe

+0

@Joe No. Eseguirà un Overriden virtuale Execute, se ne esiste uno. – Scott

+0

Quindi forse è solo un trucco per ottenere quel metodo 'protetto' e non' pubblico' allora. – Joe

risposta

6

Questo codice consente di eseguire l'override del metodo Execute.

Ricordare che un metodo di interfaccia normalmente implementato è pubblico (e non virtuale o astratto), quindi non è possibile sovrascriverlo nelle classi derivate e la creazione di un nuovo metodo Execute non sarebbe accessibile tramite l'interfaccia IController per impostazione predefinita (senza questa interfaccia alla tecnica virtuale protetta). Creando un metodo virtuale protetto (che chiamate dal metodo di interfaccia implementato esplicitamente) consente alle classi derivate di sovrascrivere il metodo Execute senza interrompere l'implementazione dell'interfaccia.

Ho trovato un ottimo articolo su questo qui: C# Overriding Interface Methods in Subclasses

+0

Quindi, essenzialmente, se voglio esporre alcune funzionalità tramite l'interfaccia che voglio cambiare in una sottoclasse, posso usare questo modello. –

+0

Perché preferire questo schema di progettazione a 'public virtual Execute (RequestContext requestContext)'? – Scott

+2

@Scott che utilizza virtual public consentirebbe l'accesso da questa classe senza un riferimento all'interfaccia IController. Sarebbe pubblico. L'utilizzo protetto mantiene il metodo interno alla classe ControllerBase e ai suoi discendenti a meno che non si abbia un riferimento esplicito all'interfaccia IController. Quindi è meglio protetto e usato solo quando vi si accede molto intenzionalmente. – BenSwayne

2

Secondo MSDN Documentation, uno scopo dell'implementazione esplicita dei membri dell'interfaccia è: "Poiché le implementazioni esplicite dei membri dell'interfaccia non sono accessibili tramite le istanze di classe o di struttura, consentono l'esclusione delle interfacce di interfaccia dall'interfaccia pubblica di una classe o di una struttura. è particolarmente utile quando una classe o una struttura implementano un'interfaccia interna che non interessa il consumatore di quella classe o struttura. "

Se la mia interpretazione di quanto sopra è corretta, una variabile con tipo ControllerBase non può essere utilizzata per chiamare Execute perché è protetta. Il tipo della variabile deve essere IController. Non sono sicuro se questo è l'intento del costrutto, ma sembra che questo sia il motivo.

Nelle prove pertinenti, hanno espressamente trasmesso le variabili ControllerBase a IController prima di chiamare Execute.

+0

Sì. Forse è solo un modo elegante per oscurare la chiamata Execute dall'esterno. – Scott

+1

@Scott La mia ipotesi è che questo sia usato per rafforzare la separazione delle responsabilità. Se si detiene un riferimento 'ControllerBase', non si intende eseguirlo. Se si tiene un 'IController', si ha intenzione di eseguirlo solo. – vhallac

1

A prima vista questo schema di progettazione sembrerebbe non servire a nulla. Tuttavia, fornisce l'opportunità per la classe ControllerBase di apportare in seguito modifiche senza interruzioni all'implementazione dell'interfaccia IController. Le modifiche sarebbero garantite per l'esecuzione, poiché non si basa sulle classi ereditate che chiamano base.Execute(). Forse questo potrebbe essere usato per gestire i contesti o la sicurezza in futuro?

Forse lo sviluppatore preferisce mantenere una separazione logica dell'interfaccia con un'implementazione sovrascrivibile.