【问题标题】:Internal Interface implementation内部接口实现
【发布时间】:2012-01-04 00:52:01
【问题描述】:

直截了当:我有一个类实现了两个接口:

public class A : Interface1, Interface2{
   // Interface 1 implementation...
   // Interface 2 implementation...
}

有没有办法(不创建另一个新类)使 Interface1 实现内部化并从其他组件隐藏它(只有 Interface2 将保持公开)?

编辑: 一些更有用的信息:Interface1Interface2 在另一个核心组件中被定义为公共并且无法更改。

提前致谢,

【问题讨论】:

  • 将接口设为内部? internal interface Interface1 其他,不,因为接口定义为公共合同。
  • 谢谢,很遗憾这两个界面都是公开的,无法更改(见编辑)
  • 嗯......如果......创建一个新的接口internal interface Interface3 : Interface1并在目标类中实现它,所以Interface1仍然是公共的,但我们会得到我们想要的。对不起,我错了,这不起作用

标签: c# .net interface


【解决方案1】:

虽然您可以将接口本身设为内部,但这些方法仍然是公共 API 的一部分。您可以选择显式接口实现,以便接口定义的 API 仅通过接口可见,而不通过类可见。

interface IFoo
{
     void M();
}

interface IBar
{
     void X(); 
}

public class Bar : IBar, IFoo
{
    public void X() // part of the public API of Bar
    {
    }

    void IFoo.M() // explicit implementation, only visible via IFoo
    {
    }
}

Bar bar = new Bar();
bar.X(); // visible
bar.M(); // NOT visible, cannot be invoked
IFoo foo = bar;
foo.M(); // visible, can be invoked

除此之外,如果您希望世界从不知道该类支持该接口,那么您只需要不让该类实现该接口。接口用于广播给定对象明确或以其他方式支持给定行为的意图。如果那不是你想要的,你需要换个方向。可能只是该类将行为实现为私有实现细节,无接口。另一种方法是将这些实现铲到私有嵌套类中。

public class Bar : IBar
{
    Foo foo = new Foo();

    public void X() { }   

    public void DoSomething()
    {
        this.foo.M(); // invokes method of instance of nested class
    }

    class Foo : IFoo
    {
        public void M() { } 
    }
}

在这种方法下,世界永远不知道一个类履行接口​​契约,因为它在技术上不。契约由Foo 履行,世界看不到Foo .但是,好处是如果类需要调用需要接口的外部定义的方法,它仍然可以将嵌套类实例传递给这些方法。

【讨论】:

  • +1 感谢您的回答。这似乎接近我所需要的。但是,我一直在寻找一种完全禁止IFoo foo = bar; 的方法,这可能吗?
  • @GETah,如果将显式接口实现 结合使用内部接口,则可以有效地限制对给定库的访问。如果您不控制接口定义(如您的情况),这不是一个选项。
  • @GETah,请参阅更新的答案以获取更多想法(cmets 已修改并与代码一起添加以回答)。
  • 谢谢,我的班级需要填写 Interface1 的原因是因为我还有其他需要该服务的内部班级。我对您的回答非常满意,非常感谢您的时间和精力:)
【解决方案2】:

没有办法将强制转换操作限制在接口上。但是,您可以提供一个实现接口但通常不可用的包装类。

例如:

public class Foo
{
    private IFoo wrap = new WrapFoo(this);

    internal IFoo GetIFoo()
    {
        return wrap;
    }

    private class WrapFoo : IFoo
    {
        public WrapFoo(Foo parent)
        {
            //Save parent
        }

        public void DoSomething()
        {
            //Implement interface
        }
    }
}

另一种更复杂的方法是使用代码签名来验证调用者是库,否则抛出异常。

【讨论】:

    猜你喜欢
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    相关资源
    最近更新 更多