部分隐藏外部程序集的接口方法

Posted

技术标签:

【中文标题】部分隐藏外部程序集的接口方法【英文标题】:Partially hide interface methods for external assemblies 【发布时间】:2011-12-05 03:06:46 【问题描述】:

我正在寻找将一个接口中的方法“发布”到另一个接口的方法,但为其他接口隐藏它。

我有以下接口

public interface IFirst

  void Forbidden();


public interface ISecond

  void Test(IFirst first);


internal class Second : ISecond 

  void Test(IFirst first)
  
    first.Forbidden();
  

如您所见,ISecond 的实现需要在 IFirst 上调用“Forbidden”方法。但是,我不想让另一个程序集中的类在 IFirst 的实现上调用“禁止”。我可以做些什么来向外界隐藏这个方法,但仍然允许 ISecond 的实现使用它?

【问题讨论】:

【参考方案1】:

Forbidden 方法放在另一个非公共接口中:

public interface IFirst

  // whatever ...


internal interface IPrivate : IFirst

    void Forbidden();


public interface ISecond

  void Test(IFirst first);


internal class Second : ISecond 

  void Test(IFirst first)
  
    var priv = first as IPrivate;
    if (priv != null)
        priv.Forbidden();
  

【讨论】:

我会从 IFirst 派生 IPrivate 并要求每个 IPrivate 也是 IFirst。 @DonAndre,是的,这是我的意图,但我在打字时忘记了...感谢您指出 虽然如果IFirst 的所有实例也实现IPrivate,这将起作用,但没有什么可以阻止某人使用IFirst 的实现,它没有实现IPrivate,然后这将不工作 我确实喜欢创建一个内部派生接口的想法,但 Sam 是对的:那么仍然无法保证 Test() 确实通过了 IPrivate 实例。我想要一个说明对 IPrivate 的要求的方式(因此在某种程度上,对 Forbidden 方法的要求)所以 ISecond.Test 保证收到 IPrivate,但同时我想禁止其他人使用 Forbidden 方法... 嗯,没有办法让界面成员不公开,所以我猜你被卡住了......我担心没有理想的解决方案。【参考方案2】:

看看internal keyword 和internalsvisibleto attribute。结合这些,你应该能够做你想做的事。请注意:这适用于您的程序集的所有内部。

【讨论】:

我已经仔细阅读了您提到的文档。但是,我认为在这里仅使用访问修饰符是不可能的,因为它们需要应用于 Forbidden() 方法......这是一种接口方法,因此不允许访问修饰符(我希望允许它,尽管:-) ) 好吧,从您的示例代码中并没有明显看出 IFirst 还包含其他需要公开的方法。如果是这种情况,我仍然可以推荐这个,但 IFirst 分为“内部 IFirstForbidden”和“公共 IFirst”。【参考方案3】:

如果你想要接口,我认为你无能为力,就像你想要一个公共方法 ISecond 来获取 IFirst 的参数然后 IFirst 必须是公共的,所以必须所有的方法,所以IFirst 的用户总是可以调用这些方法。

您可以测试IFirst 的实现,您可以查看它是否实现了另一个内部接口,但除非您可以控制传递正在传递的IFirst 的实现,否则不能保证有效(即使您可以控制分发实例,也不能保证工作),因为有人总是可以传入一些其他不实现内部接口的实现。

你也许可以通过使用抽象基类来做到这一点,但我没有对此进行测试,只是一个想法:

public abstract class FirstBase

   protected internal abstract void Forbidden();


public interface ISecond

  void Test(FirstBase first);


internal class Second : ISecond 

  void Test(FirstBase first)
  
    first.Forbidden();
  

【讨论】:

虽然我真的很喜欢这两种解决方案(感谢 Sam 和 Thomas!)我现在选择了这个解决方案。指定该方法 ISecond.Test() 需要一个 IFirst 的实例,而实际上它需要一个更具体的接口使得 ISecond 接口的使用价值降低:它创建了一个 IFirst 是“足够”的建议,这是不正确的。当然,使用抽象基类也有缺点(如果只是因为它是接口和实际实现之间的额外层,并且它不允许多重继承),对于“外部”世界(其他程序集)来说更清楚。

以上是关于部分隐藏外部程序集的接口方法的主要内容,如果未能解决你的问题,请参考以下文章

C# 防止 AppDomain 程序集的类实例访问文件

背水一战 Windows 10 (122) - 其它: 通过 Windows.System.Profile 命名空间下的类获取信息, 查找指定类或接口的所在程序集的所有子类和子接口

将 [ThreadStatic] 属性应用于外部程序集中的方法

对具有引用程序集的应用程序进行数字签名的正确方法

x86LinuxGNUGNOME是什么

使用来自另一个 MEF 程序集的类而不引用它