簡體   English   中英

如何強制調用C#派生方法

[英]How to force call a C# derived method

我有一個由某些工具生成的類,因此無法更改。 生成的類非常簡單(沒有接口,沒有虛擬方法):

class GeneratedFoo
{
  public void Write(string p) { /* do something */ }
}

在C#項目中,我們希望提供一種方法,以便我們可以插入MyFoo的其他實現。 所以我正在考慮使MyFoo派生自GeneratedFoo

class MyFoo : GeneratedFoo
{
  public new void Write(string p) { /* do different things */ }
}

然后,我有一個CreateFoo方法,該方法將返回GeneratedFoo或MyFoo類的實例。 但是,它總是在GeneratedFoo中調用該方法。

GeneratedFoo foo = CreateFoo(); // if this returns MyFoo,
foo.Write("1"); // it stills calls GeneratedFoo.Write

因為這不是虛擬方法,所以可以避免這種情況。 但是我想知道是否有一種方法(也許是hack)使其稱為派生方法。

謝謝,
伊恩

亞當給你答案(正確的答案)。 現在是時候要求您入侵了:)


class BaseFoo
{
    public void Write() { Console.WriteLine("Hello simple world"); }
}

class DerFoo : BaseFoo
{
    public void Write() { Console.WriteLine("Hello complicated world"); }
}

public static void Main()
{
    BaseFoo bs = new DerFoo();
    bs.Write();

    bs.GetType().GetMethod("Write").Invoke(bs, null);
}

打印輸出:

Hello simple world
Hello complicated world

如果無法將方法虛擬化,則不會。 非虛擬方法在編譯時是靜態鏈接的,不能更改。

編寫一個安全廣播到派生類型的擴展方法,然后針對引用調用該方法。

public static class Extensions
{
  public static void WriteFoo(this GeneratedFoo foo, string p)
  {
     MyFoo derived = foo as MyFoo;
     if (derived != null)
     {
        derived.Write(p);
     }
     else
     {
        foo.Write(p);
     }
  }
}

然后用

GeneratedFoo unknownFoo;
unknownFoo.WriteFoo("win");

注意 :這是一個骯臟的hack。 一個更清晰的解決方案是問自己, 為什么首先需要使用new修飾符。 重載Write(p)的含義會使維護人員感到困惑。 您可以很容易地將其聲明為public void WriteToTarget()或更具體的名稱,以首先避免這種混淆。

在一個方法上使用“ new”不會被覆蓋,它會隱藏原始方法。 這與多態性完全不同,應該避免,它的唯一目的是實現相同功能的方法(例如public Foo Clone()和public new Bar Clone();)的協方差/反方差。 當同名方法添加到您無法控制且此時無法更改方法名稱的基類中時,另一個用途是用於遺留代碼。

盡管這兩個方法使用相同的名稱,但它們是完全獨立的方法,但是在類的方法表中它占據了一個不同的位置,在此,重寫取代了類方法表中的現有方法。

我對此的解決方案是使用諸如IFoo之類的接口,並編輯生成的類或使用將其所有方法調用委派給GeneratedFoo實例的代理類以實現IFoo。


public DelegatingFoo : IFoo
{
  private GeneratedFoo foo;

  public DelegatingFoo(GeneratedFoo foo) { this.foo = foo; }
  public void Write(string p) { foo.Write(p); }
}

如果生成的類沒有虛方法,則不可能。 如果可以修改工具以將Write方法生成為虛擬方法,則在MyFoo中使用關鍵字override而不是new來限定Write方法。 第二種選擇是編寫腳本/宏以在工具運行后在所需方法之前插入字符串“ virtual”來更改GeneratedFoo的源代碼,這是構建過程的一部分。

添加到構建系統的自定義FX cop規則如何處理?

您可以使用的一種方法是實際上定義一些新類,這些類都從GeneratedFoo派生。 例如:

public class MyFooBase : GeneratedFoo
{
    public virtual void MyMethod() { ... }
}

public class MyFoo1 : MyFooBase { ... }

public class MyFoo2 : MyFooBase { ... }

這實際上將使您可以將虛擬方法添加到生成的類中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM