Можете ли вы подключить интерфейс к определенному классу

Вот ситуация. В некоторых случаях я нахожу себя в классе, пусть называет его class C, который имеет те же функции, что и class A, но с добавлением, что он имеет interface B. Пока я делаю это так:

class C : A,B
{
   //code that implements interface B, and nothing else
}

Проблема придет, если class A окажется запечатанным. Есть ли способ сделать class A реализовать interface B без необходимости определять class C (с помощью методов расширения или что-то еще)

Ответ 1

В принципе: нет. Это часть того, что "mixins" может привести к таблице, но С# languauge в настоящее время не поддерживает это (это обсуждалось несколько раз, IIRC).

Вам нужно будет использовать ваш текущий подход или (чаще всего) только сквозной декоратор, который инкапсулирует A, а не наследует A.

class C : IB
{
    private readonly A a;
    public C(A a) {
        if(a == null) throw new ArgumentNullException("a");
        this.a = a;
    }

    // methods of IB:
    public int Foo() { return a.SomeMethod(); }
    void IB.Bar() { a.SomeOtherMethod(); }
}

Ответ 2

Единственный способ, который я вижу, - изменить наследование на агрегацию, например:

class C : B
{
    public C(A instanceToWrap)
    {
        this.innerA = instanceToWrap;
    }

    //coda that implements B

    private A innerA;
}

Кажется, есть возможность внедрить интерфейс во время выполнения, как это делается с помощью Array class и IEnumerable<T> interface, но это кажется немного излишним.

Ответ 3

Есть ли способ сделать класс A реализовать интерфейс B без необходимости определять класс C (с помощью методов расширения или что-то еще)

Короткий ответ - нет. Вы не можете сделать A реализовать B, потому что у вас нет элемента управления A. Тем не менее, я думаю, что вы направились по правильной дороге с помощью методов расширения. Рассмотрим это:

public static class AImplementsBExtensions
{
    public static void Func1(this A o) { }
    public static void Func2(this A o) { }
}

Теперь я не знаю, какие существуют методы на B, но вы можете реализовать B на A, если вы не можете наследовать его.

Помните, что это не реализация.. Если вы добавите или удалите методы из интерфейса, вам придется сделать это вручную. Но теперь вы можете сделать это:

var a = new A();
a.Func1();

Ответ 4

Вы можете попробовать создать свой класс без наследования: class C : B и как обертка вокруг A.

Кроме того, вы можете предоставить неявные операторы преобразования, чтобы код типа A obj = new C(new A()) работал аналогично тому, как будет работать производный класс.

class C : B
{
    private A _inner;
    public C(A inner)
    {
        this._inner = inner;
    }

    public A Inner { get { return this._inner; } }

    public static implicit operator A(C obj)
    {
        return obj == null ? (A)null : obj._inner;
    }

    public static implicit operator C(A obj)
    {
        return new C(obj);
    }
}