假设组件(比如CompA)在SDK中公开了一个公共C#.NET类(比如Base):
namespace CompA { public abstract class Base {} }
另一个组件(比如ExtB)通过派生这个基类来扩展CompA:
namespace ExtB { class Derived : CompA.Base {} }
您有什么看法,不允许声明类ExtB.Derived为 public 的最佳方法是什么? CompA.Base用于扩展 CompA,但不用于使用它公开新的公共API。
namespace ExtB { public class Derived : CompA.Base {} } // DISALLOW
我能想到的是期望公开API的程序集用.NET自定义属性标记,并用另一个.NET自定义属性标记基类。加载这些程序集的产品将不允许加载这样的程序集,以暴露/发布从使用自定义属性标记的类型派生的类型。
CompA的AssemblyInfo.cs:
[assembly:SdkApiAssemblyAttribute()]
ExtB的AssemblyInfo.cs:
[assembly:SdkApiAssemblyAttribute()]
Base.cs:
namespace CompA
{
[Publishable(false)]
public abstract class Base {}
}
谢谢!
答案 0 :(得分:1)
首先,它听起来你做错了什么。在确认您的意图只是为了防止意外暴露类型之后,这听起来很合理。编写单元测试可能很简单,但如果派生类不是代码库的一部分,则可以执行以下操作。
没有编译时间方法来阻止这种情况(AFAIK)。只需检查Base类构造函数中的类型并抛出异常。
public abstract class Base
{
protected Base()
{
if (this.GetType().IsPublic)
throw new InvalidOperationException("Type is not meant to be exposed public");
}
}
public class Der : Base
{
public Der()
{
}
}
这将阻止客户端创建Der
的新实例(如果它被声明为public
。
注意:有些情况下构造函数无法运行,那么你运气不好。幸运的是,他们是角落案件,不必担心太多。例如:FormatterServices.GetUninitializedObject不会运行构造函数。
答案 1 :(得分:0)
@SriramSakthivel,你是对的:我做错了什么! :)
虽然没有故意我没有说CompA.Base实际上不是一个类,而是一个接口!
public interface Base
{
string ShouldNotBePublic();
}
基类应该使用 protected 访问修饰符公开方法:
public abstract class Base
{
protected string ShouldNotBePublic();
}
这样,派生类不会意外地暴露受保护的信息。然后,组件CompA可以通过实现模板方法模式来访问此方法:
namespace CompA
{
public abstract class Base : IBaseInternal
{
protected string ShouldNotBePublic();
string IBaseInternal.ShouldNotBePublic()
{
return ShouldNotBePublic();
}
}
internal interface IBaseInternal
{
string ShouldNotBePublic();
}
}
很抱歉这个混乱。