在分部类中重写虚方法

本文关键字:重写 方法 | 更新日期: 2023-09-27 18:19:20

我目前正在使用nopCommerce源代码,并尽我所能避免编辑源代码,而是使用与源代码分开的部分类和插件,如果我们需要升级版本的话。

我想通过在同一个程序集中使用部分类来对下订单的代码进行一些更改:

原始源代码:

namespace Nop.Services.Orders {
  public partial class OrderProcessingService : IOrderProcessingService {
        public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest)
        { //....

我的局部类:

namespace Nop.Services.Orders {
  public partial class OrderProcessingService : IOrderProcessingService {
    public override PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest) { //....

当我尝试编译这段代码时,我得到一个错误:

Nop.Services.Orders类型"。OrderProcessingService'已经定义了一个具有相同参数类型的名为'PlaceOrder'的成员

但是我使用的是override,原始类中的方法是virtual,有人能告诉我我在哪里出错了,以及我如何重写这个方法?

在分部类中重写虚方法

不能在同一个类上重写虚方法。分部类只是同一个类的定义在不同的地方分开,它没有定义层次结构,所以这是不可能的

可以将类、结构或接口的定义拆分为两个或多个源文件。每个源文件都包含类定义的一部分,并且在编译应用程序时将所有部分组合在一起

您应该创建一个继承类来实现您的目标

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

不完全清楚你想要什么,但也许你可以使用 partial方法?

因此,负责类的第一个"部分"的"一方"可以单独给出签名:

"原始源代码":

namespace Nop.Services.Orders {
  public partial class OrderProcessingService : IOrderProcessingService {
    partial void PlaceOrder(ProcessPaymentRequest processPaymentRequest,
      ref PlaceOrderResult result);

然后,负责其他"部分"的"一方"可能会也可能不会选择提供该方法的实现。如果他们提供一个,它看起来像:

"My partial class":

namespace Nop.Services.Orders {
  public partial class OrderProcessingService : IOrderProcessingService {
    partial void PlaceOrder(ProcessPaymentRequest processPaymentRequest,
      ref PlaceOrderResult result) {
      // actual code goes here
    }

注意事项:

  • partial方法不能为public;它必须是私有的,甚至指定private关键字都是非法的。并且私有方法不允许是virtual
  • partial方法必须返回void,不能有标记为out的参数,因此我们将result作为ref参数
  • 第一部分中的声明用分号;代替正文
  • 另一个"部分"的实现,如果它存在,有一个方法体{ ... }

现在在"原始源代码"中,该方法可以像这样调用:

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

注意:

  • 如果没有类的"部分"选择实现PlaceOrder,则在编译之前,该方法(包括对它的所有调用!)将从类的所有部分中(精神上)删除。这也删除了调用中参数的求值,如果该求值有副作用(例如PlaceOrder(FindRequestAndCauseOtherEffects(), ref result);),这可能很重要。
  • 我前面提到的方法必须返回void并且没有out参数的限制可以理解为其结果。

今天的partial void方法课程到此结束

你不能那样做。partial的基本作用是告诉c#编译器将这两段代码连接在一起。

有一个很蹩脚的解决方案是完成类,然后从它继承并覆盖你想要的方法,例如这里有一个简单的例子:

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

你可以使用分部类把一个类的代码分成多个,但是你不能把一个方法分成两个分部类。你只需要在一个地方有方法。如果你想扩展功能,那么寻找其他方法,如子类化或组合等,这适合你的场景。

问题是,从技术上讲,你仍然在同一个类。在编译时,部分类本质上是组合在一起的,所以它看到的是在同一个类中定义的两个方法。如果您使用子类,您可以这样做,但您不能在同一个类中定义两次方法。