2013-06-21 11 views
5

Ich arbeite derzeit mit dem nopCommerce Quellcode und versuche mein Bestes, die Bearbeitung der Quelle überhaupt zu vermeiden, sondern stattdessen Teilklassen und Plugins, die getrennt vom Quellcode sind, sollten wir jemals müssen Versionen aktualisieren.Überschreiben Sie eine virtuelle Methode in einer partiellen Klasse

Ich möchte einige Änderungen an dem Code machen, die einen Auftrag, durch eine partielle Klasse in derselben Baugruppe mit:

Orignal Source Code:

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

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

Meine Teilklasse:

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

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

Wenn ich versuche, diesen Code zu kompilieren, bekomme ich einen Fehler:

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

Aber ich benutze override und die Methode in der ursprünglichen Klasse ist virtual, könnte mir jemand sagen, wo ich hier falsch liege, und wie ich diese Methode überschreiben könnte?

+0

'override' und' virtual' steht für Vererbung, 'partielle' Klassen gelten nicht als Vererbung. – Matthew

+0

gibt es eine andere Möglichkeit, die Methode zu überschreiben? Ich denke, der Grund, warum nopCommerce partielle Klassen überall verwendet, ist, dass Erweiterungen vorgenommen werden können, ohne den Quellcode zu ändern. – DevDave

+2

Typischerweise werden 'partielle' Klassen in Verbindung mit automatisch generiertem Code verwendet. Um die Methode 'PlaceOrder' zu überschreiben, würden Sie eine Klasse erstellen, die' OrderProcessingService' erbt. – Matthew

Antwort

6

Sie können eine virtuelle Methode in derselben Klasse nicht überschreiben. Partielle Klassen sind nur die gleiche Klasse mit der Definition an verschiedenen Stellen aufgeteilt, ist es nicht eine Hierarchie definieren, so dass ist einfach nicht möglich

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

Sie sollten eine vererbte Klasse erstellen Ihr Ziel

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

danke Claudio, das ist die Antwort, nach der ich suche, denke ich, ein bisschen spät am Tag! – DevDave

2

Das Problem ist, dass Sie immer noch technisch in der gleichen Klasse sind. Partielle Klassen werden im Wesentlichen kombiniert, wenn kompiliert wird, also sieht es beide Methoden in der gleichen Klasse definiert. Wenn Sie eine Unterklasse verwenden, können Sie das tun, aber Sie können die Methode nicht zweimal in derselben Klasse definieren.

3

zu erreichen Sie können eine Teilklasse verwenden, um den Code einer Klasse in mehrere Teile aufzuteilen, aber Sie können keine einzelne Methode in 2 Teilklassen aufteilen. Sie müssen eine Methode nur an einem Ort haben. Wenn Sie die Funktionalität erweitern möchten, suchen Sie nach anderen Methoden wie Sub-Classing oder Komposition usw., die zu Ihrem Szenario passen.

+0

Es gibt jedoch partielle ungültige Methoden. –

2

Sie können das nicht tun. Was partial grundsätzlich tut, ist dem C# -Compiler zu sagen, dass er die beiden Bits des Codes zusammenfügt.

Ein bisschen eine hacky Lösung ist es, die Klasse zu beenden, und dann erben davon und überschreiben die Methoden, die Sie wollen, z. Hier ist ein einfaches Beispiel:

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

nicht ganz klar, was Sie wollen, aber vielleicht können Sie eine partial Methode verwenden?

So ist die „Partei“ verantwortlich für den ersten „Teil“ der Klasse kann die Signatur alleine geben:

„Orignal Source Code“:

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

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

Dann wird die „Partei“ verantwortlich für der andere "Teil" kann oder darf sich nicht dafür entscheiden, eine Implementierung des Verfahrens zu liefern.Wenn sie ein liefern, sieht das wie:

"Mein Teil-Klasse":

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

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

     // actual code goes here 
    } 

Dinge zu beachten:

  • die partial Methode nicht public sein kann; Es muss privat sein und es ist illegal, das Schlüsselwort private anzugeben. Und eine private Methode darf nicht virtual sein.
  • die partial Methode muss void zurückkehren und mit out markiert hat keine Parameter, so setzten wir die result als ref Parameter
  • die Deklaration in dem ersten „Teil“ hat ein Semikolon ; statt einen Körper
  • die Umsetzung in dem anderen „Teil“, wenn es vorhanden ist, hat eine Methode Körper { ... }

Jetzt in „Orignal Source Code“ kann das Verfahren wie folgt aufgerufen werden:

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

Beachten Sie:

  • Wenn kein „Teil“ der Klasse PlaceOrder zu implementieren wählt, die Methode ist (mental) aus allen Teilen der Klasse entfernt (einschließlich aller Anrufe zu ihm!) vor der Zusammenstellung. Dies entfernt auch die Bewertungen der Argumente in den Aufrufen, was wichtig sein könnte, wenn diese Bewertung Nebenwirkungen hätte (z. B. PlaceOrder(FindRequestAndCauseOtherEffects(), ref result);).
  • Die Einschränkungen, die ich zuvor erwähnte, dass die Methode void zurückgeben muss und keine out Parameter haben, können als eine Folge davon verstanden werden.

Ende der heutigen Lektion auf partial void Methoden.