Как работать с классом, который вы хотите расширить, который запечатан в библиотеке .NET? - PullRequest
10 голосов
/ 18 марта 2009

Я где-то читал о том, как решить проблему с желанием расширить запечатанный класс в библиотеке .NET Framework.

Это часто распространенная и полезная задача, поэтому я подумал, в таком случае, какие решения существуют? Я полагаю, что в статье, которую я прочитал, был продемонстрирован «метод» расширения запечатанного класса, но сейчас я не могу вспомнить (это были не методы расширения).

Есть ли другой способ? Спасибо

Ответы [ 7 ]

9 голосов
/ 18 марта 2009

Существует «поддельное» наследство. То есть вы реализуете базовый класс и любые интерфейсы, которые реализует другой класс:

// Given
sealed class SealedClass : BaseClass, IDoSomething { }

// Create
class MyNewClass : BaseClass, IDoSomething { }

У вас есть личный участник, я обычно называю его _backing, таким образом:

class MyNewClass : BaseClass, IDoSomething
{
   SealedClass _backing = new SealedClass();
}

Это явно не будет работать для методов с такими подписями, как:

void NoRefactoringPlease(SealedClass parameter) { }

Если класс, который вы хотите расширить, в какой-то момент наследует от ContextBoundObject, взгляните на эту статью . Первая половина - COM, вторая .Net. Он объясняет, как вы можете использовать прокси-методы.

Кроме этого, я не могу думать ни о чем.

6 голосов
/ 10 декабря 2010

этот метод, возможно, уже упоминался выше под его формальным именем, но я не знаю, это формальное имя, так что вот оно. Этот пример «расширяет» класс TextBox (пример в VB). Я считаю, что преимущество этого метода заключается в том, что вам не нужно явно кодировать или предоставлять встроенные члены. Надеюсь, что это актуально:

Модуль класса VB "MyTextBox":

public Base as TextBox, CustomProperty as Integer

Private Sub Init(newTextBox as TextBox)
    Set Base = newTextBox
End Sub

public Property Get CustomProperty2() As String
    CustomProperty2 = "Something special"
End Property

Чтобы позвонить по коду, вы можете сказать:

Dim MyBox as New MyTextBox
MyBox.Init MyForm.TextBox3

отсюда у вас есть доступ ко всем встроенным элементам, а также к вашим пользовательским элементам.

Debug.Print MyBox.Base.Text
MyBox.CustomProperty = 44

Для дополнительной полировки вы можете сделать Base свойством по умолчанию для класса, а затем опустить «Base», когда вызываете свойства Base класса. Вы называете членов Базы так:

Debug.Print MyBox().Text
MyBox().Text = "Hello World"

VBA Demo

6 голосов
/ 18 марта 2009

Методы расширения - это один из способов, альтернативой является шаблон адаптера. При этом вы пишете класс, который делегирует некоторые вызовы запечатанному, который вы хотите расширить, и добавляет другие. Это также означает, что вы можете полностью адаптировать интерфейс к тому, что ваше приложение посчитает более подходящим.

2 голосов
/ 18 марта 2009

Единственный способ «расширить» запечатанный класс без методов расширения - это обернуть его. Например:

class SuperString
{
    private String _innerString;

    public SuperString(String innerString)
    {
        _innerString = innerString;
    }

    public int ToInt() 
    {
        return int.Parse(_innerString);
    }
}

Вам нужно будет предоставить все те же методы / свойства, что и для строкового класса.

Некоторые фреймворки позволяют расширять существующие объекты. В WPF см. Свойства зависимостей . Для Windows Forms см. IExtenderProvider .

2 голосов
/ 18 марта 2009

Нет, вы не можете расширять запечатанный класс любым законным способом.

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

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

Предпочитаю композицию наследованию - по моему опыту, она намного надежнее. Подробнее об этом см. Пункт 16 в «Эффективной Java (2-е издание)».

2 голосов
/ 18 марта 2009

Может быть, использовать Шаблон декоратора ?

Помимо методов расширения, это единственная разумная техника, о которой я могу подумать.

0 голосов
/ 18 марта 2009

Как насчет методов расширения? Таким образом, вы можете «добавить» дополнительные методы, не сталкиваясь с ограничением наследования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...