我正在使用第三方c#类,它有很多很棒的方法和属性 - 但随着时间的推移,我需要使用自己的方法和属性来扩展该类。如果是我的代码,我会将该类用作我的基类并在顶部添加我自己的属性和方法 - 但是这个类有一个内部构造函数。 (在我看来,最初只是将构造函数设置为内部 - 为什么要限制子类的能力?)
我能想到的唯一一件事就是在我的课堂上创建方法/属性,这些方法/属性只是简单地调用了他们的 - 但它是一大堆代码,而且,它只是没有“感觉”正确。
有没有办法将这个类用作基类?
答案 0 :(得分:6)
你问:“为什么要限制子类的能力?”
因为继承的设计很棘手,特别是如果你正在为其他开发人员设计继承你的类。正如Josh Bloch在Effective Java中所说,你应该设计继承或禁止它。在我看来,除非你有充分的理由设计继承,否则你不应该以推测的方式这样做。
该类是否实现了您也可以实现的接口(可能通过将大多数回调代理回原始实例)?这里通常没有真正优雅的答案 - 最好的解决方案将取决于具体情况,包括你想要添加到课堂上的内容。
如果你没有添加任何更多状态 - 只是方便的方法,有效 - 那么扩展方法可能适合你。但是它们不会改变对象能够存储的数据,因此如果您需要添加自己的专用数据,那将无法正常工作。
答案 1 :(得分:3)
听起来像是扩展方法的完美应用:
“扩展方法使您能够向现有类型”添加“方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为就像它们一样对于扩展类型的实例方法。对于用C#和Visual Basic编写的客户端代码,调用扩展方法和实际在类型中定义的方法之间没有明显的区别。“
答案 2 :(得分:3)
如果类具有内部构造函数,并且没有公共构造函数,则表明设计者不打算将其子类化。在这种情况下,您可以使用封装,也可以使用扩展方法。
答案 3 :(得分:2)
仅当您的班级与您要继承的班级位于同一个程序集中时。内部构造函数将抽象类的具体实现限制为定义类的程序集。包含内部构造函数的类无法在程序集外部实例化。
答案 4 :(得分:2)
Resharper有一个很好的功能来创建委派成员。
Here是您可以使用它做的一个示例。这需要几秒钟。
答案 5 :(得分:0)
我不会讨论你是否可以围绕第三方课程建立自己的Facade。以前的作者是对的,可以按照不允许的方式设计库。假设他们有一些具有单体的耦合类,这些单体应按特定顺序或类似的方式进行初始化 - 可能存在许多第三方开发人员从不关心的设计错误(或特性),因为他们不会假设您将使用他们的图书馆就这样。
但是好吧,让我们假设构建一个外观不是一个不可能完成的任务,而你实际上只有一个问题 - 有太多的方法需要编写包装,而不是很高兴手动执行此操作。
我看到3个解决方案来解决这个问题
1)我认为新的“动态”类型的.NET 4.0将允许您解决该问题,而无需编写“英亩代码” 您应该将第三方类的实例作为具有动态关键字的私有成员封装到您的类中 您的类应该从Dynamic或实现IDynamicObject接口派生。您必须实现GetMember / SetMember函数,这些函数将所有调用转发到第三方类的封装实例
嗯,c#4.0是未来,让我们看看其他解决方案:
2)如果你有大量的公共方法(比如100多个),不要手动编写代码。我会写一个使用反射的小控制台应用程序,找到所有公共成员,然后自动生成代码来调用封装实例。例如
public type MethodName(params)
{
this.anInstanceOf3rdPartyClass.MethodName(params);
}
3)你可以像2那样做,但借助现有的反射工具,例如RedGate .NET Reflector。它将帮助您列出所有类和方法签名。然后,将所有这些粘贴到Word中,一个简单的VB宏将让您生成与2中相同的代码。 备注:只要您不复制代码,但只复制公开的复制方法签名,我认为您不会违反许可协议,但无论如何都值得重新检查