【问题标题】:Hiding an internal interface in a "friend" assembly在“朋友”程序集中隐藏内部接口
【发布时间】:2010-05-28 02:50:13
【问题描述】:

我有两个程序集:A 和 B。A 为 B 设置了 InternalsVisibleTo。我想从 A 调用以获取只能由 B 中定义的类型知道的信息,以保持内部信息。我可以使用在 A 中定义并在 B 中显式实现的内部接口来做到这一点。

程序集 A

  internal interface IHasData
  {
    Data GetData();
  }

  class ClassA 
  {
    DoSomething(IHasData);
  }

大会B

  public abstract class ClassB : IHasData
  {
    Data IHasData.GetData() { /** do something internal **/ }
  }

当有人引用程序集 B 并从 ClassB 派生时,麻烦就来了 - 他们得到错误:“类型 'AssemblyA.IHasData' 是在未引用的程序集中定义的”,即使该类型对他们来说应该是不可见的。如果我查看公共类型定义,我会看到我所期望的 - 没有实现接口的 ClassB。

为什么会出现此错误?所有的实现都在程序集 B 中。我可以在 ClassB 内部使用 IHasData,这不需要引用程序集 A。有人可以帮我了解发生了什么吗?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    这是一个有趣的发现,但看起来当引用暴露了这些依赖项时,引用引用的依赖项的规则仍然适用于显式接口实现。我在here 之前已经回答了一些关于此的问题。

    更好的解决方案是支持组合而不是继承,并在程序集 B 未公开的内部类中定义 IHasData 的实现。大致如下:

      public abstract class ClassB
      {
        class HasData : IHasData
        {
          HasData(ClassB b) {m_b = b;}
          Data IHasData.GetData() { m_b.GetData(); }
        }
    
        private readonly HasData m_hasData;
    
        public ClassB() {
          m_hasData = new HasData(this);
        }
    
        internal Data GetData() { 
          /** do something internal **/ 
        }
      }
    

    【讨论】:

    • +1 以获得可靠的方法。我会考虑添加一个内部隐式运算符来将ClassB 的实例也转换为IHasData。那么ClassB 仍然可以在内部使用就好像它是一个IHasData
    • 谢谢。是的,这将完全以一种偷偷摸摸的隐式运算符诡计的方式起作用。不过,在这个实现中,HasData 的工作是委托给 ClassB,因此这些方法可能无论如何都可用。我的首选方法是在HasData 类中尽可能多地包含IHasData 逻辑,并限制它对ClassB 的依赖。
    • 这种方法的问题是程序集 A 更难以使用它 - 尽管可以按照 Mark 的建议解决这个问题。你知道这种限制是否有原因吗?
    • 不,你需要一位 C# 编译器大师来解释这一点:))
    【解决方案2】:

    ClassB 在其程序集之外是公开可见的,因此它的所有基类型——类和接口——也必须是公开可见的。除非您也为该程序集提供 InternalsVisibleTo,否则从不同程序集中的 ClassB 派生的内容将无法看到 IHasData

    ClassB 也显式实现了IHasData,这意味着默认情况下实现是公共的。

    【讨论】:

      猜你喜欢
      • 2022-12-02
      • 2011-12-05
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多