Избавляемся от директив прекомпилятора в C #
-
27-10-2019 - |
Вопрос
Меня попросили поддерживать некоторый код, который не является устаревшим, как я бы хотел, и он пронизан директивами компилятора, что делает его практически нечитаемым и почти таким же удобным в обслуживании. Показательный пример:
родовое слово Директивы using
еще красивее:
Я подумал, что дам ConditionalAttribute
попробовать, но в данной ситуации это не сработает
Есть ли способ выбраться из этого кошмара директив компилятора?
Код скомпилирован в соответствии с .NET 3.5
.
ОБНОВЛЕНИЕ:
Одед ответил, предлагая удалить директивы компилятора вокруг метода BeforeAdd
, что приведет к его перегрузке. К сожалению, это не сработает, поскольку оба метода должны переопределять класс AbstractBusiness
, который предоставляет две разные реализации в зависимости от того, какие сборки в конечном итоге будут включены:
или
родовое словоЭтот код получает свои зависимости от набора библиотек, созданных компанией когда-то в прошлом и с тех пор "обновляющихся". Теперь у них есть 4 разные версии этого набора библиотек с конфликтующими пространствами имен и разными реализациями. И все во имя «обратной совместимости» с приложениями, использующими (очень) старые версии.
< sizesЗАКЛЮЧЕНИЕ
В итоге я выбрал ответ @Oded, потому что он имеет наибольший смысл в качестве общего подхода ( KISS и все такое). Однако я не мог использовать его в этом случае; то, что вы видите здесь, - это лишь верхушка айсберга. Я бы не хотел, чтобы K.I.S.S. этот код, если он мне заплатил.
Решение
В первом случае похоже, что вместо этой конструкции у вас может быть просто несколько перегрузок метода.На этом этапе решение перегрузки должно позаботиться обо всем.
Во втором случае (с использованием директив) вы можете задать псевдоним для некоторых директив и включить их все, используя псевдоним там, где это необходимо.Что произойдет, если будут включены все пространства имен?Есть ли конфликты имен?
Другие советы
Я бы сказал, что проблема не в этом классе. Этот урок - всего лишь симптом. Проблема в базовом классе, вызывающем BeforeAdd. Если вы можете там провести рефакторинг, тогда вам не понадобятся условные компиляции.
Если у вас есть конфликтующие имена и пространства имен, вы можете обойти это с помощью ключевого слова using (не для сборок).
Итак, вы можете сделать что-то вроде
родовое словоЯ также думаю, что проблема в базовом классе, а не в этом классе как таковом.
В этом случае вы можете обойти эту ерунду, используя либо адаптацию, либо интерфейс.
Я не знаю, как называется другой класс, но допустим, что он называется EntityAggregator.
родовое словозатем в базовом классе вашего агрегатора:
родовое словозатем в вашем подклассе:
родовое словоТеперь вы можете адаптировать другие объекты к IEntity, реализовав этот интерфейс.
Когда я смотрю на этот код, мне также кажется, что, возможно, вы используете события вместо этого кода.
Теперь, если вы говорите о компиляции для многократного использования, когда код компилируется в двух разных местах при двух разных условиях, вы можете сделать это более изящно, используя частичные классы.
Вы изолируете код CONDITION_1 примерно так:
родовое словоМне в данном случае это не нравится из-за повторения кода. Вы можете помочь в этом с помощью ключевого слова using:
родовое словоСудя по тому, что я вижу, похоже, что исходный разработчик не имел никакого представления о наследовании и полиморфизме.Это немного сложно сказать по коду, но кажется, что LogEntity и AbstractBusinessEntity имеют общие свойства.Есть ли модель наследования или это два совершенно не связанных класса?Если они не связаны, не могли бы вы создать модель наследования или интерфейс, который они оба могут реализовать?Может помочь, если вы вставите классы.
Короче говоря, я бы не стал тратить время на попытки работать с этим кодом в его нынешнем виде.Я бы нашел способ любой ценой отменить директивы компилятора.Не похоже, что его полностью восстановить, но это может потребовать некоторых усилий.
Не знаю, практично ли это, но я бы создал ветки в моем DVCS, Mercurial, чтобы справиться с этим.
У меня будет две ветки в игре и третья временно, пока я исправляю ошибки / добавляю общий код.
Вот как я бы создал начальные версии:
родовое словоЧтобы исправить ошибки только в одном из них:
родовое словоЧтобы исправить распространенные ошибки:
родовое словоПримечание . Предполагается, что вы не собираетесь проводить жесткий рефакторинг ни в типовых, ни в общих ветвях. Если вы это сделаете, то, вероятно, вам будет лучше с текущей ситуацией, по крайней мерепо сравнению с таким ветвистым способом.Любой такой рефакторинг сделает будущее слияние действительно болезненным.