【问题标题】: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 的实现使用它?

【问题讨论】:

    标签: c# interface access-modifiers


    【解决方案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 keywordinternalsvisibleto 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 是“足够”的建议,这是不正确的。当然,使用抽象基类也有缺点(如果只是因为它是接口和实际实现之间的额外层,并且它不允许多重继承),对于“外部”世界(其他程序集)来说更清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2018-09-16
    • 1970-01-01
    相关资源
    最近更新 更多