如何强制调用C#衍生方法(How to force call a C# derived method

2019-08-01 04:58发布

我有一个由一些工具所产生的一类,所以我不能改变它。 生成的类是非常简单的(没有界面,没有虚拟方法):

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

在C#项目,我们希望提供一种方式,以便我们能在不同的实现MyFoo的插头。 所以我想实现从GeneratedFoo衍生MyFoo

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

这是expceted,因为它不是一个虚拟的方法。 但我不知道是否有一种方法(一劈也许),使其调用派生方法。

谢谢,
伊恩

Answer 1:

如果不能够使该方法虚拟的,没有。 非虚拟方法是在编译时静态链接的,并且不能被改变。



Answer 2:

亚当给了你一个答案(正确的)。 现在是时候为你要求的黑客:)


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


Answer 3:

编写safecasts您的派生类型,并呼吁针对的参考,而不是方法的扩展方法。

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");

:这是一个肮脏的黑客。 更明确的解决办法是要问自己, 为什么你需要使用new修饰符摆在首位。 超载的意思Write(p)将让你的代码混淆的维护者。 你可以很容易地将它声明public void WriteToTarget()或一些更具体的,以避免在首位的是混乱。



Answer 4:

使用“新”上的方法不重写,它隐藏了原来的方法。 这是为了多态性完全不同的,应该避免,其唯一目的是用于执行相同的功能的方法协方差/双重方差(例如,公共的Foo克隆();和公共新酒吧克隆())。 另一个目的是为旧代码时的相同名称的方法添加到您在无法控制,不能在这个时候改变你的方法名称的基类。

虽然这两种方法共享相同的名字,他们是完全不同的方法,它占据了类的方法表中的不同插槽,其中作为压倒一切的替换类的方法表中现有的方法。

我对这个解决方案是使用诸如IFoo的接口,并可以编辑生成的类或使用代理类,代表所有的方法调用GeneratedFoo的实例来实现IFoo的。


public DelegatingFoo : IFoo
{
  private GeneratedFoo foo;

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


Answer 5:

如果生成的类没有虚方法则是不可能的。 如果你可以修改生成Write方法虚拟然后MyFoo工具使用关键字覆盖,而不是新的资格Write方法。 第二个选择是写一个脚本/宏运行此工具所需的方法作为构建过程的一部分之前注入字符串“虚拟”后更改GeneratedFoo的源代码。



Answer 6:

添加到您的构建系统有关的自定义FX警察规则是什么?



Answer 7:

你可以使用将实际上定义了一些新的类都是从GeneratedFoo衍生的方法; 例如:

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

public class MyFoo1 : MyFooBase { ... }

public class MyFoo2 : MyFooBase { ... }

这将让你的虚拟方法基本上添加到您的生成的类。



文章来源: How to force call a C# derived method