一种无需在 C# 中创建新的 class 即可扩展现有 class 的方法

A way to extend existing class without creating new class in c#

我有一个很好的完整 class,它正在做很棒的事情。我需要通过替换其中的一些方法来允许用户使用这个 class,但是不允许继承,因为这个 class 也用于其他应用程序 classes.

这就像你有一个 class 创建了一个 table,但你需要允许用户重新定义创建 table 单元格的方法,让用户打印自定义内容在这个牢房里。然而,class 有一种默认方式来打印单元格内容(以防用户不需要自定义它)。

是否有任何通用或标准化的方法来实现这一点?

已更新

“花生画廊”指出我的方法(底部)不符合要求,这是另一种方式:

使用委派。使用 Action 或 Func 类型定义某些 public 属性。在您的代码中需要调用这些行为的地方,将属性与 null 进行比较。如果为空,则使用您的默认行为。如果不是,调用值。

您的调用代码可以设置属性,但不是必须的。

(第一次尝试)替代方法:

您描述的是扩展方法,或者继承的使用(如果可用)。

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.

https://msdn.microsoft.com/en-us//library/bb383977.aspx

Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics (or pillars) of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive. If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

https://msdn.microsoft.com/en-us/library/ms173149.aspx

您无法从所有 .NET 类型派生,但您可以为它们编写扩展方法。

假设您能够修改现有的 class,您应该将您的方法标记为 virtual

这将允许您提供默认实现(这是您现有代码将使用的)并能够在需要时使用自定义实现覆盖它。

您的基础 class 可能类似于:

public class TableMaker
{
    public virtual string MakeTable()
    {
        //Provide default implementation used by existing code here
    }
}

您的继承 class 然后可以覆盖虚拟方法:

public class SpecialTableMaker : TableMaker
{
    public override string MakeTable()
    {
        //Provide specific implementation for cell text here
    }
}

您现有的代码可以正常工作,您可以在需要的地方使用其他 class。

我终于用这个解决方案结束了。它是由@codenoir 提出的,但是我也有一个演示整个机制的代码。

public class MyTable
{
    public delegate string OnInsertHandler();
    public event OnInsertHandler OnInsert;


    public string Show()
    {
        string res = "-BEGIN-";
        if (OnInsert != null) {
            res += OnInsert ();
        } else {
            res += "#default insert#";
        }

        res += "-END-";

        return res;
    }
}


public class DelegateTester
{

    public void OnTest()
    {
        MyTable mt = new MyTable();

        Debug.Log("Default output: " + mt.Show());  // Shows "-BEGIN-#default insert#-END-"

        // Changing functionality via delegate
        mt.OnInsert += MyCustomInsert;

        Debug.Log("Customized output: " + mt.Show());   // Shows "-BEGIN-#custom insert#-END-"

        // Remove delegate
        mt.OnInsert -= MyCustomInsert;

        Debug.Log("Rollbacked output: " + mt.Show());   // Shows "-BEGIN-#default insert#-END-"
    }

    public string MyCustomInsert()
    {
        return "#custom insert#";
    }
}

在此示例中,我使用的是使用 Func 委托扩展的 MyTable class。这样我就可以允许我的软件模块的用户只扩展一种方法而不会弄乱其他 classes 和对象。