Подтвердить что ты не робот

Внедрение внутреннего интерфейса

Прямо к проблеме: у меня есть класс, который реализует два интерфейса:

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

Есть ли способ (без создания другого нового класса) сделать внутреннюю реализацию Interface1 и скрыть ее от других компонентов (только интерфейс2 останется открытым)?

EDIT:. Еще одна полезная информация: Interface1 и Interface2 определяются как общедоступные в другом базовом компоненте и не могут быть изменены.

Спасибо заранее,

4b9b3361

Ответ 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. Однако преимущество заключается в том, что если классу необходимо вызвать внешние методы, требующие интерфейса, он все равно может передать экземпляр вложенного класса этим методам.

Ответ 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
        }
    }
}

Еще одним сложным способом было бы использовать подписание кода для проверки того, что вызывающий объект является библиотекой и иначе выбрасывает исключение.