Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override a virtual method in a partial class

I am currently working with the nopCommerce source code and trying my best to avoid editing the source at all, but instead using partial classes and plugins that are separate from the source code, should we ever need to upgrade versions.

I want to make some changes to the code that places an order, by using a partial class in the same assembly:

Orignal Source Code:

namespace Nop.Services.Orders {

  public partial class OrderProcessingService : IOrderProcessingService {

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

My partial class:

namespace Nop.Services.Orders {

  public partial class OrderProcessingService : IOrderProcessingService {

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

When I try to compile this code I get an error:

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

But I am using override and the method in the original class is virtual, could someone tell me where I am going wrong here, and how I could override this method?

like image 215
DevDave Avatar asked Jun 21 '13 17:06

DevDave


1 Answers

Not entirely clear what you want, but maybe you can use a partial method?

So the "party" responsible for the first "part" of the class can give the signature alone in:

"Orignal Source Code":

namespace Nop.Services.Orders {

  public partial class OrderProcessingService : IOrderProcessingService {

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

Then the "party" responsible for the other "part" may or may not choose to supply an implementation of the method. If they supply one, that will look like:

"My partial class":

namespace Nop.Services.Orders {

  public partial class OrderProcessingService : IOrderProcessingService {

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

      // actual code goes here
    }

Things to note:

  • the partial method cannot be public; it must be private and it is illegal to even specify the private keyword. And a private method is not allowed to be virtual.
  • the partial method must return void and cannot have parameters marked with out, so we put the result as a ref parameter
  • the declaration in the first "part" has a semicolon ; instead of a body
  • the implementation in the other "part", if it exists, has a method body { ... }

Now in "Orignal Source Code" the method can be called like this:

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

Be aware:

  • If no "part" of the class chooses to implement PlaceOrder, the method (including all calls to it!) is (mentally) removed from all parts of the class before compilation. This also removes the evaluations of the arguments in the calls, which could be important if that evaluation had side effects (e.g. PlaceOrder(FindRequestAndCauseOtherEffects(), ref result);).
  • The restrictions I mentioned earlier that the method must return void and have no out parameters can be understood as a consequence thereof.

End of today's lesson on partial void methods.

like image 124
Jeppe Stig Nielsen Avatar answered Oct 20 '22 04:10

Jeppe Stig Nielsen