在“友元”程序集中隐藏内部接口

3
我有两个程序集:A和B。 A已经设置了InternalsVisibleTo,可以让B访问它的内部成员。 我想以一种保持内部性的方式从A中进行调用,以获取只能由B中定义的类型知道的信息。我可以通过在A中定义一个内部接口,并在B中显式实现来实现这一点。
  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。请帮我理解发生了什么?
2个回答

3
这是一个有趣的发现,但是当引用公开了其依赖项时,仍然适用于显式接口实现中引用你的引用的依赖项的规则。我以前回答过一些关于这个问题的问题,可以在这里看到。
更好的解决方案是优先使用组合而不是继承,并在Assembly 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 **/ 
    }
  }

这是一个可靠的方法。我会考虑添加一个内部的隐式操作符来将 ClassB 的实例转换为 IHasData。然后 ClassB 可以在内部继续被使用,好像它是一个 IHasData - Mark Rushakoff
谢谢。是的,这种偷偷摸摸的隐式操作符技巧完全可行。但在这个实现中,“HasData”的工作是委托给“ClassB”,因此那些方法可能已经可用了。我更喜欢的方法是尽可能将“IHasData”逻辑包含在“HasData”类中,并限制其对“ClassB”的依赖。 - Igor Zevaka
这种方法的问题在于对于组件A来说更难以消化它,尽管可以像Mark建议的那样解决这个问题。你知道这个限制存在的原因吗? - dmo
不好意思,你需要一位C#编译器大师来解释这个问题:)) - Igor Zevaka

0

ClassB 是在其程序集外公开可见的,因此它的所有基类型 -- 类和接口 -- 也必须是公开可见的。从不同程序集派生的东西将无法看到 IHasData,除非您为该程序集提供了一个 InternalsVisibleTo

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接