2013-06-21 28 views
5

我目前正在使用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) { //.... 

当我尝试编译此代码时,出现错误:

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

但我使用的是override和原始类中的方法是virtual,有人可以告诉我我在哪里出错了,以及我如何覆盖此方法?

+0

'override'和'virtual'是为了继承,'partial'类不被认为是继承。 – Matthew

+0

是否有一些其他方式来覆盖该方法?我认为nopCommerce在所有地方都使用部分类的原因是,可以在不改变源代码的情况下进行扩展 – DevDave

+2

通常,“partial”类与自动生成的代码结合使用。为了'覆盖'PlaceOrder方法,你需要创建一个继承'OrderProcessingService'的类。 – Matthew

回答

6

您不能在同一个类上覆盖虚拟方法。部分类只是同一类分裂在不同的地方定义,所以这是不可能的它并没有定义一个层次

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

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

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

感谢克劳迪奥,这就是我正在寻找的答案,我想,今天有点晚! – DevDave

2

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

3

您可以使用部分类将多个类的代码拆分,但不能将2个部分类中的单个方法拆分。你只需要在一个地方有方法。如果你想扩展功能,然后寻找其他方法,如子分类或组合等,这些都适合你的场景。

+0

但是,存在“部分空白”方法。 –

2

你不能那样做。基本上,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() { } 
} 
4

尚不完全清楚自己想要什么,但也许你可以使用一个partial方法

“一部开拓创新的源代码”:

因此,“党”,负责班级的第一“部分”可以单独给签名

namespace Nop.Services.Orders { 

    public partial class OrderProcessingService : IOrderProcessingService { 

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

那么“方”负责其他“部分”可能会或可能不会选择提供该方法的实现。如果他们提供一个,这将是这样的:

“我的部分类”:

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方法的课。