如何将对父 class 的所有呼叫转移到子 class?

How to divert all calls to parent class to child class?

假设我有一个引用包含 Class1 的 dll 的 C# 项目。在 Project1 中,我想通过使用继承自 Class1 的名为 Class2 的 class 来扩展 Class1 的功能,然后我想在需要 Class1 时使用 Class2( 而无需将对 Class1 的调用修改为指向Class2,这是key)。

此外,我必须添加 Class1 是一个初始化模块(在我正在使用的框架中),它没有被显式调用(它是内部机制的一部分)。 这意味着在我的代码中让 Class2 扩展了 Class1 的行为后,我不能简单地去替换 Class2 对 Class1 的调用。

(如何)可以做到这一点?

我想到的另一个想法是使用部分 classes;但是,我怀疑是否有可能在该 dll 之外将完整的 class 重新定义为 'later' 的部分 class。

===== 后来编辑:我看到一篇文章似乎暗示这是可能的,我正在尝试弄清楚如何做到这一点。看,在这篇文章中,它具有从 dll 中的 IInitializableModule (Class1) 继承的 RestrictFileTypes (Class2),但它没有说明 Class2 从那时起如何替换 Class1 的所有调用,向前发展 (http://world.episerver.com/blogs/al-higgs/dates/2012/11/Restricting-the-file-types/)。你怎么看待它?

我不明白第二个要求("Moreoever...")。至于第一个,我看到了两种方式。

您可以编写class2,然后通过手动编辑交换class1 和class2 的名称。出现的次数应该很少,只有 cs 文件名和构造函数。像您通常在交换操作中所做的那样,首先使用中间名称可能会省事。这可能是最简单和最干净的方法,但您可能无法控制当前的 class1 并且无法重命名它。所以这是另一种方式。

您从头开始再次将 class2 命名为 class1,但在不同的命名空间中。您将有一个 class1 从不同命名空间中的另一个 class1(旧的)下降。完成后,在每个引用旧 class1 的文件中为新命名空间放置一个 using 指令,并确保它是最后一个 using 行,以便它优先于它上面的那些。如果当前 class1 不是引用它的同一个命名空间的成员,这应该有效。如果是后者,则必须将新名称空间的声明插入到现有名称空间的所有声明中:

namespace ns.of.old.class1
{
    namespace ns.of.new.class1
    {
        [...]
        Some reference to / use of class1
    }
}

using 指令技巧很脆弱,有人可能会注意到指令不是按字母顺序排列的,然后右键单击它们,选择 "Remove and Sort"。然后您的代码可能会被破坏或更糟:仍然可以编译但再次使用旧的 class1。

我称之为 多态性 并通过继承实现,如下所示:

using System;

namespace polymorphismExample {
    public class class1 {
        public virtual string A => "I am Class1.A";
        public         string B => "I am Class1.B";
    }
    public class class2 : class1 {
        public override string A => "I am Class2.A";
    //    public override string B => "I am Class1.B";
        public    new   string B => "I am Class2.B";
    }

    class Program {
        static void Main(string[] args) {
            class1 a1_1 = new class1();

            class1 b1_2 = new class2();
            class2 b2_2 = new class2();

            Console.WriteLine("{0}: {1}", "a1_1.A", a1_1.A);
            Console.WriteLine("{0}: {1}", "a1_1.A", a1_1.B);
            Console.WriteLine();

            Console.WriteLine("{0}: {1}", "b1_2.A", b1_2.A);
            Console.WriteLine("{0}: {1}", "b1_2.A", b1_2.B);
            Console.WriteLine();

            Console.WriteLine("{0}: {1}", "b2_2.A", b2_2.A);
            Console.WriteLine("{0}: {1}", "b2_2.A", b2_2.B);
            Console.WriteLine();   
            Console.ReadLine();
        }
    }
}

输出为:

a1_1.A: I am Class1.A  
a1_1.A: I am Class1.B

b1_2.A: I am Class2.A  
b1_2.A: I am Class1.B

b2_2.A: I am Class2.A  
b2_2.A: I am Class2.B

注意class2中的注释行是因为不能编译;因为方法 B 在 class1 中不是虚拟的。此模式要求 class1 不是 密封的 class,并且只有 class1 中的方法被标记为 虚拟(或者当然是 abstract)将表现出所需的行为:即使在声明为 class1 类型的变量上调用时也会调用 class2 行为.

当然,在任何时候,变量都必须使用 class2 构造函数进行初始化。