2013-06-21 12 views
5

Attualmente sto lavorando con il codice sorgente nopCommerce e sto facendo del mio meglio per evitare di modificare l'origine del tutto, ma utilizzando invece classi parziali e plugin che sono separati dal codice sorgente, dovremmo mai necessità di aggiornare le versioni.Sovrascrivere un metodo virtuale in una classe parziale

voglio fare alcune modifiche al codice che effettua un ordine, utilizzando una classe parziale nello stesso assembly:

Orignal Source Code:

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

     public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest) 
     { //.... 

mia classe parziale:

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

    public override PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest) { //.... 

Quando provo a compilare questo codice ottengo un errore:

Type 'Nop.Services.Orders.OrderProcessingService' already defines a member called 'PlaceOrder' with the same parameter types

Ma sto usando override e il metodo nella classe originale è virtual, qualcuno potrebbe dirmi dove sto andando male qui, e come potrei scavalcare questo metodo?

+0

'override' e' virtual' è per ereditarietà, le classi 'parziali' non sono considerate ereditarietà. – Matthew

+0

c'è un altro modo per sovrascrivere il metodo? Penso che la ragione per cui nopCommerce usi le classi parziali ovunque sia così che le estensioni possano essere fatte senza alterare il codice sorgente – DevDave

+2

In genere le classi 'partial' sono usate in congiunzione con il codice generato automaticamente. Per "sovrascrivere" il metodo 'PlaceOrder', dovresti creare una classe che eredita' OrderProcessingService'. – Matthew

risposta

6

Non è possibile eseguire l'override di un metodo virtuale sulla stessa classe. classi parziali sono solo la stessa classe con la definizione spacco sui posti differenti, non definisce una gerarchia in modo che è solo non è possibile

It is possible to split the definition of a class or a struct, or an interface over two or more source files. Each source file contains a section of the class definition, and all parts are combined when the application is compiled

è necessario creare una classe ereditata per raggiungere il tuo obiettivo

public class MyOrderProcessingService : OrderProcessingService 
{ 
    public override PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest) { //.... 
} 
+0

grazie Claudio, questa è la risposta che sto cercando, penso, arrivando un po 'tardi! – DevDave

2

Il problema è che sei ancora tecnicamente nella stessa classe. Le classi parziali sono essenzialmente combinate durante la compilazione, quindi ciò che vede sono entrambi i metodi definiti nella stessa classe. Se hai usato una sottoclasse, puoi farlo, ma non puoi avere il metodo definito due volte nella stessa classe.

3

Puoi utilizzare la classe parziale per dividere il codice di una classe in più, ma non puoi dividere un singolo metodo in 2 classi parziali. Devi avere un metodo in un solo posto. Se si desidera estendere la funzionalità, cercare altri metodi come la sottoclasse o la composizione ecc. Che si adatta sempre al proprio scenario.

+0

Tuttavia, esistono metodi 'partial void'. –

2

Non puoi farlo. Quello che è partial fondamentalmente è dire al compilatore C# di unire i due bit di codice insieme.

Un po 'una soluzione hacky consiste nel completare la classe, quindi ereditare da quella e sovrascrivere i metodi desiderati, ad es. ecco un semplice esempio:

public partial class A 
{ 
    public virtual void X() { } 
} 
public partial class A 
{ 
    public void Y() { } 
} 
public class B : A 
{ 
    public override void X() { } 
} 
4
Non

del tutto chiaro ciò che si vuole, ma forse si può utilizzare un metodopartial?

Così il "partito" responsabile della prima "parte" della classe può dare la firma da solo in:

"codice sorgente Orignal":

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

    partial void PlaceOrder(ProcessPaymentRequest processPaymentRequest, 
     ref PlaceOrderResult result); 

Poi il "partito" responsabile l'altra "parte" può o non può scegliere di fornire un'implementazione del metodo.Se essi forniscono uno, che sarà simile:

"La mia classe parziale":

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

    partial void PlaceOrder(ProcessPaymentRequest processPaymentRequest, 
     ref PlaceOrderResult result) { 

     // actual code goes here 
    } 

cose da notare:

  • il metodo partial non può essere public; deve essere privato ed è illegale specificare anche la parola chiave private. E un metodo privato non può essere virtual.
  • metodo partial deve restituire void e non possono avere parametri contrassegnati con out, in modo da mettere il result come ref parametro
  • dichiarazione nella prima "parte" ha una virgola ; invece di un corpo
  • all'attuazione nell'altra "parte", se esiste, ha un corpo del metodo { ... }

Ora in "Orignal codice sorgente" il metodo può essere chiamato in questo modo:

// ... 
PlaceOrderResult result = null; 
PlaceOrder(someRequest, ref result); 
// check if 'result' was changed to something non-null, and if so use 'result' 

Essere consapevoli:

  • Se nessuna "parte" della classe sceglie di implementare PlaceOrder, il metodo è (mentalmente) rimossi da tutte le parti della classe (tra cui tutte le chiamate ad essa!) prima della compilazione. Ciò rimuove anche le valutazioni degli argomenti nelle chiamate, che potrebbero essere importanti se tale valutazione avesse effetti collaterali (ad esempio PlaceOrder(FindRequestAndCauseOtherEffects(), ref result);).
  • Le restrizioni che ho menzionato in precedenza che il metodo deve restituire void e non hanno parametri out possono essere interpretate come una conseguenza di ciò.

Fine della lezione di oggi sui metodi partial void.