Есть ли способ получить из класса с внутренним конструктором? - PullRequest
9 голосов
/ 17 июня 2009

Я работаю со сторонним классом c #, который имеет много замечательных методов и свойств, но со временем мне нужно расширить этот класс с помощью собственных методов и свойств. Если бы это был мой код, я бы просто использовал этот класс в качестве своего базового класса и добавил свои собственные свойства и метод поверх него, но у этого класса есть внутренний конструктор. (По моему мнению, это было короткое место, чтобы сделать конструктор внутренним во-первых - зачем ограничивать возможность подкласса?)

Единственное, о чем я мог подумать, - это создать метод / свойства в моем классе, которые бы просто вызывали их - но это акры кода и, ну, в общем, он просто "не чувствует" себя правильным.

Есть ли способ использовать этот класс базовым классом?

Ответы [ 6 ]

6 голосов
/ 17 июня 2009

Вы спрашиваете: «Зачем ограничивать возможности подкласса?»

Поскольку проектирование для наследования является сложным делом, особенно если вы разрабатываете для других разработчиков наследование от вашего класса. Как говорит Джош Блох в «Эффективной Java», вы должны создать наследство или запретить его. На мой взгляд, если у вас нет веских оснований для проектирования наследования, вы не должны делать это умозрительно.

Реализует ли класс интерфейс, который вы также можете реализовать (возможно, передавая большинство вызовов обратно экземпляру оригинала)? Здесь часто нет действительно элегантного ответа - и наилучшее решение будет зависеть от конкретной ситуации, включая то, что вы пытаетесь добавить в класс.

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

3 голосов
/ 17 июня 2009

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

3 голосов
/ 17 июня 2009

Звучит как идеальное приложение для методов расширения:

Документы с расширением MSDN

«Методы расширения позволяют вам« добавлять »методы к существующим типам без создания нового производного типа, перекомпиляции или иного изменения исходного типа. Методы расширения являются особым видом статического метода, но они вызываются так, как если бы они были методы экземпляра для расширенного типа. Для клиентского кода, написанного на C # и Visual Basic, нет очевидной разницы между вызовом метода расширения и методами, которые фактически определены в типе. "

2 голосов
/ 17 июня 2009

Resharper имеет хорошую функцию для создания делегирующих членов.

Здесь - это пример того, что вы можете с ним сделать. Это займет пару секунд.

2 голосов
/ 17 июня 2009

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

0 голосов
/ 17 июня 2009

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

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

Я вижу 3 решения для решения именно этой проблемы

1) Я полагаю, что новые «динамические» типы .NET 4.0 позволят вам обойти эту проблему без необходимости писать «акры кода» Вы должны инкапсулировать экземпляр стороннего класса в свой класс как привилегированный член с динамическим ключевым словом Ваш класс должен быть производным от Dynamic или реализовывать интерфейс IDynamicObject. Вам нужно будет реализовать функции GetMember / SetMember, которые будут перенаправлять все вызовы инкапсулированному экземпляру класса третьей стороны

Что ж, c # 4.0 - это будущее, давайте посмотрим на другие решения:

2) Не пишите код вручную, если у вас есть значительное количество открытых методов (скажем, более 100). Я написал бы небольшое консольное приложение, которое использует отражение и находит все открытые члены, а затем автоматически генерирует код для вызова инкапсулированного экземпляра. Например

public type MethodName(params)
{
   this.anInstanceOf3rdPartyClass.MethodName(params);
}

3) Вы можете сделать то же, что и 2, но с помощью существующих инструментов отражения, например RedGate .NET Reflector. Это поможет вам перечислить все сигнатуры классов и методов. Затем вставьте все это в Word, и простой макрос VB позволит вам сгенерировать тот же код, что и в 2. Примечание: Как только вы не копируете код, а только копируете сигнатуры методов, которые являются общедоступными, я не думаю, что вы нарушите лицензионное соглашение, но в любом случае стоит перепроверить

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