2013-05-24 29 views
7

Ho una classe con alcune funzioni virtuali, facciamo finta questo è uno di loro:metodi virtuali Quando si esegue il un'istanza di una classe

public class AClassWhatever 
{ 
    protected virtual string DoAThingToAString(string inputString) 
    { 
     return inputString + "blah"; 
    } 
} 

voglio creare un'istanza di questa classe, mentre l'override "DoAThingToAString" in linea, proprio come ho possono dichiarare le proprietà inline in una dichiarazione, come segue:

... 

AClassWhatever instance = new AClassWhatever 
{ 
    DoAThingToAString = new function(string inputString) 
    { 
     return inputString + inputString + " fill my eyes." 
    } 
} 

... 

E ora per "istanza", DoAThingToAString viene sostituito con tale definizione. Devo essere in grado di definire il comportamento predefinito nella definizione della classe e solo sovrascriverlo in base alle esigenze, in momenti diversi e non voglio proliferare un gruppo di sottoclassi per farlo.

So che ho bisogno di usare delegati o qualcosa di simile, ma sono stato fuori dal gioco della sintassi per troppo tempo e Google mi stava dando troppe informazioni irrilevanti.

risposta

6

È possibile utilizzare i delegati o Func s per eseguire questa operazione.

In primo luogo, aggiungere questo alla classe AClassWhatever:

public Func<string, string> DoAThingToAString = (x) => x + "blah"; 

Ora è possibile utilizzare la stessa sintassi per ignorare l'azione.

AClassWhatever instance = new AClassWhatever() 
{ 
    DoAThingToAString = (x) => x + x + " fill my eyes." 
}; 
+0

Questa è la sintassi ero cercando, ma una domanda stupida. In DoAThingToAString, sto usando un metodo di estensione controller chiamato da un'azione controller in quanto tale: 'this.DoExtensionMethod (someString);' Non ho più un riferimento a "questo" ora che sono all'interno di Func definizione. C'è un modo per ottenere un riferimento al chiamante o devo passarlo insieme al mio altro input? – kamii

+2

@kamii, dovrai passare un riferimento all'oggetto o qualsiasi altro valore specifico di cui hai bisogno. Questa è una funzione anonima, quindi non ha idea dell'istanza. (per favore, controlla me). – gunr2171

5

Non si può farlo con i metodi, ma si poteva fare l'equivalente con i delegati/metodi anonimi:

public class AClassWhatever 
{ 
    public AClassWhatever() 
    { 
     this.DoAThingToAString = this.DoAThingToAStringImpl; 
    } 

    public Func<string, string> DoAThingToAString { get; set; } 

    protected virtual string DoAThingToAStringImpl(string input) 
    { 
     return input + input + " fill my eyes."; 
    } 
} 

Usage:

var instance = new AClassWhatever 
{ 
    DoAThingToAString = inputString => inputString + inputString + 
     " fill my eyes something other than the default behavior." 
} 

var result = instance.DoAThingToAString("input"); 

Nota che inputString => inputString + inputString + "..." è lo stesso come x => x + x + "..."

+0

"Devo essere in grado di definire il comportamento predefinito nella definizione della classe ..." – mellamokb

+0

@mellamokb Ho modificato la mia risposta per fornire un'implementazione predefinita nel costruttore. – Dan

+0

Ti sto dando la risposta per una migliore codifica, ma forse hai una risposta alla domanda di riferimento al chiamante che ho chiesto a gunr2171 nei commenti? – kamii

0

Perché non definire una proprietà delegata e usa quella definizione se esiste quando viene chiamato il metodo? Nella tua istanziazione dell'oggetto, puoi fornire una definizione alternativa usando la proprietà.

Ad esempio:

public MyDelegateTypeThatMatchesMyFunctionCall DoAThingToAStringProperty { get; set; } 

public class AClassWhatever 
{ 
    protected virtual string DoAThingToAString(string inputString) 
    { 
     var handler = this.DoAThingToAStringProperty; 
     if (handler) 
     { 
      return handler(inputString); 
     } 

     // do default behavior 
     return inputString + "blah"; 
    } 
} 

Se si vuole garantire che la vostra proprietà delegato sostituisce qualsiasi definizione override del metodo virtuale che si possa fare in questo modo:

public MyDelegateTypeThatMatchesMyFunctionCall DoAThingToAStringProperty { get; set; } 

public class AClassWhatever 
{ 
    protected string DoAThingToAString(string inputString) 
    { 
     var handler = this.DoAThingToAStringProperty; 
     if (handler) 
     { 
      return handler(inputString); 
     } 

     // do default behavior 
     return DoAThingToAStringInternal(inputString); 
    } 

    protected virtual string DoAThingToAStringInternal(string inputString) 
    { 
     // do default behavior 
     return inputString + "blah"; 
    } 
} 
Problemi correlati