简体   繁体   English

一种扩展现有类而不在C#中创建新类的方法

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

I have a good complete class which is doing awesome things. 我有一个很好的完整班级,正在做很棒的事情。 I need to allow users to use this class by replacing some methods in it, but inheritance is not allowed, because this class also used in other application classes. 我需要允许用户通过替换其中的某些方法来使用此类,但是不允许继承,因为此类也用于其他应用程序类中。

It is like you have a class which creating a table, but you need to allow users to redefine method which is creating table cell to let the user print something custom in this cell. 就像您有一个创建表的类,但是您需要允许用户重新定义创建表单元格的方法,以使用户在此单元格中打印自定义内容。 The class, however, has a default way to print the cell content (in case the user do not need to customize it). 但是,该类具有打印单元格内容的默认方式(以防用户不需要自定义它)。

Is there any common-used or standartized way to achieve this? 是否有任何常用或标准化的方法来实现这一目标?

Updated 更新

Having had "the peanut gallery" point out that my approach (at bottom) wouldn't fit the bill, here's another way: 有“花生画廊”指出,我的方法(底部)不符合要求,这是另一种方法:

Use delegation. 使用委托。 Define certain public properties with type Action or Func. 使用Action或Func类型定义某些公共属性。 Where these behaviors need to be invoked in your code, compare the properties to null. 需要在代码中调用这些行为的地方,将属性与null进行比较。 If null, use your default behavior. 如果为null,请使用默认行为。 If not, invoke the values. 如果不是,则调用值。

Your calling code MAY set the properties, but doesn't have to. 您的调用代码可以设置属性,但不必设置。

(first try) Alternative approaches: (首先尝试)替代方法:

You are describing an extension method, or the use of inheritance if that's available. 您正在描述一种扩展方法,或者在可能的情况下使用继承。

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. 对于用C#和Visual Basic编写的客户端代码,在调用扩展方法和在类型中实际定义的方法之间没有明显的区别。

https://msdn.microsoft.com/en-us//library/bb383977.aspx https://msdn.microsoft.com/zh-CN//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. 如果ClassC派生自ClassB,而ClassB派生自ClassA,则ClassC继承在ClassB和ClassA中声明的成员。

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

You can't derive from all .NET types, but you can write extension methods for them. 您不能派生所有.NET类型,但可以为它们编写扩展方法。

Assuming you are able to modify the existing class, you should be marking your method as virtual . 假设您能够修改现有的类,则应将方法标记为virtual

This will allow you to provide a default implementation (which is what your existing code will use) and be able to override it with a custom one where needed. 这将允许您提供默认的实现(这是现有代码将使用的实现),并能够在需要时使用自定义代码覆盖它。

Your base class could be something along the lines of: 您的基类可能类似于:

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

Your inheriting class can then override the virtual method: 然后,您的继承类可以覆盖虚拟方法:

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

You existing code will work just fine and you can use this other class where you need it. 您现有的代码可以正常工作,您可以在需要时使用其他类。

I've finally ended with this solution. 我终于以这个解决方案结束了。 It was proposed by @codenoir, however I also have a code which demonstrates a whole mechanism. 它是由@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#";
    }
}

In this example I am using MyTable class which is extended using Func delegate. 在此示例中,我使用MyTable类,该类通过Func委托进行了扩展。 This way I can allow to users of my software module to extend only one method without make any mess with others classes and objects. 这样,我可以允许软件模块的用户仅扩展一种方法,而不会与其他类和对象造成任何混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM