我有一个由一些工具所产生的一类,所以我不能改变它。 生成的类是非常简单的(没有界面,没有虚拟方法):
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,因为它不是一个虚拟的方法。 但我不知道是否有一种方法(一劈也许),使其调用派生方法。
谢谢,
伊恩
如果不能够使该方法虚拟的,没有。 非虚拟方法是在编译时静态链接的,并且不能被改变。
亚当给了你一个答案(正确的)。 现在是时候为你要求的黑客:)
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
编写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()
或一些更具体的,以避免在首位的是混乱。
使用“新”上的方法不重写,它隐藏了原来的方法。 这是为了多态性完全不同的,应该避免,其唯一目的是用于执行相同的功能的方法协方差/双重方差(例如,公共的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); }
}
如果生成的类没有虚方法则是不可能的。 如果你可以修改生成Write方法虚拟然后MyFoo工具使用关键字覆盖,而不是新的资格Write方法。 第二个选择是写一个脚本/宏运行此工具所需的方法作为构建过程的一部分之前注入字符串“虚拟”后更改GeneratedFoo的源代码。
添加到您的构建系统有关的自定义FX警察规则是什么?
你可以使用将实际上定义了一些新的类都是从GeneratedFoo衍生的方法; 例如:
public class MyFooBase : GeneratedFoo
{
public virtual void MyMethod() { ... }
}
public class MyFoo1 : MyFooBase { ... }
public class MyFoo2 : MyFooBase { ... }
这将让你的虚拟方法基本上添加到您的生成的类。