C# 有没有一种方法可以从具有内部构造函数的类派生?

C# 有没有一种方法可以从具有内部构造函数的类派生?,c#,constructor,design-patterns,C#,Constructor,Design Patterns,我正在使用一个第三方c#类,它有很多很棒的方法和属性——但是随着时间的推移,我需要用我自己的方法和属性扩展这个类。如果它是我的代码,我只会使用这个类作为基类,并在上面添加我自己的属性和方法——但这个类有一个内部构造函数。(在我看来,首先让构造函数内部化的位置很短——为什么要限制子类的能力?) 我能想到的唯一一件事就是在我的类上创建方法/属性,这些方法/属性只是简单地调用了它们的方法/属性——但这需要大量的代码,而且,它“感觉”不对 是否有任何方法可以将此类用作基类?仅当您的类与要从中继承的类位于

我正在使用一个第三方c#类,它有很多很棒的方法和属性——但是随着时间的推移,我需要用我自己的方法和属性扩展这个类。如果它是我的代码,我只会使用这个类作为基类,并在上面添加我自己的属性和方法——但这个类有一个内部构造函数。(在我看来,首先让构造函数内部化的位置很短——为什么要限制子类的能力?)

我能想到的唯一一件事就是在我的类上创建方法/属性,这些方法/属性只是简单地调用了它们的方法/属性——但这需要大量的代码,而且,它“感觉”不对


是否有任何方法可以将此类用作基类?

仅当您的类与要从中继承的类位于同一程序集中时。内部构造函数将抽象类的具体实现限制为定义该类的程序集。包含内部构造函数的类不能在程序集之外实例化。

听起来像是扩展方法的完美应用程序:


“扩展方法使您能够”添加方法将复制到现有类型,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被调用时就像它们是扩展类型上的实例方法一样。对于用C#和Visual Basic编写的客户机代码,调用扩展方法和在类型中实际定义的方法之间没有明显的区别。“

如果类有一个内部构造函数,并且没有公共构造函数,那么这表明设计者并不打算将其子类化。在这种情况下,您可以使用封装,也可以使用扩展方法。

您会问:“为什么要限制子类的能力?”

因为为继承而设计是很棘手的,特别是当您为其他开发人员设计从您的类继承时。正如Josh Bloch在《高效Java》中所说的,您应该为继承而设计,或者禁止继承。在我看来,除非你有一个很好的理由为继承而设计,否则你不应该这样做

该类是否实现了您也可以实现的接口(可能通过将大多数调用代理回原始类的实例)?这里通常没有真正优雅的答案——最佳解决方案取决于具体情况,包括您试图添加到类中的内容


如果您没有添加任何更多的状态-只是方便的方法,那么扩展方法可能对您很有用。但它们不会改变对象能够存储的数据,因此,如果您需要添加自己的专用数据,这将不起作用。

我不会讨论您是否可以围绕该第三方类构建自己的外观。以前的作者是对的,库的设计方式可能不允许这样做。假设他们有一些耦合类,这些类有单例,应该按照特定的顺序或类似的方式初始化-可能有很多设计错误(或特性),第三方开发人员从不关心,因为他们不认为您将以这种方式使用他们的库

但是好吧,让我们假设构建门面并不是一项不可能完成的任务,事实上您只有一个问题-有太多的方法需要编写包装,而手动编写包装并不好

我认为有3种解决方案可以解决这个问题

1) 我认为新的.NET4.0“动态”类型将允许您在不必编写“大量代码”的情况下解决该问题 您应该使用dynamic关键字将第三方类的实例作为privare成员加入到您的类中 您的类应该从动态接口或实现IDynamiObject接口派生。您必须实现GetMember/SetMember函数,该函数将所有调用转发给第三方类的封装实例

好吧,c#4.0是一个未来,让我们看看其他解决方案:

2) 如果有大量的公共方法(比如超过100个),不要手动编写代码。我将编写一个小型控制台应用程序,它使用反射并查找所有公共成员,然后自动生成代码来调用封装的实例。比如说

public type MethodName(params)
{
   this.anInstanceOf3rdPartyClass.MethodName(params);
}
3) 您可以执行与2相同的操作,但需要借助现有的反射工具,例如RedGate.NET Reflector。它将帮助您列出所有类和方法签名。然后,将所有这些粘贴到Word中,一个简单的VB宏将让您生成与在2中相同的代码。
备注:只要您不复制代码,而只是复制公开的方法签名,我认为您不会违反许可协议,但无论如何,值得重新检查一下

Resharper有一个很好的功能来创建委派成员


这是一个你能用它做什么的例子。这需要几秒钟。

您只需像以前一样“新建”它—它神奇地获得了您添加到其中的新方法。扩展方法只适用于可以使用静态方法的地方。此外,还必须包括包含具有扩展方法的类的命名空间。例如,您不能拥有存储状态的属性。了解状态-存在限制。我不理解你对静态方法的评论-当然,扩展方法是静态的,但它可以通过'this'参数访问对象实例。第一部分:第二部分: