Переход от основных конструкторов

Предварительный просмотр С# 6 для Visual Studio 2013 поддерживает функцию основных конструкторов, которую команда решила не вносить в финальную версию. К сожалению, моя команда реализовала более 200 классов с использованием первичных конструкторов.

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

Прежде чем я потрачу много времени на создание такого зверя, есть ли там кто-нибудь, кто уже сделал это или знает лучший способ?

Ответ 1

Как я и предложил в комментариях, вы можете использовать версию Roslyn, которая знает о первичных конструкторах для синтаксического анализа кода в дереве синтаксиса, а затем модифицирует это синтаксическое дерево вместо использования "обычного" конструктора. Имейте в виду, что вы должны поместить все инициализаторы, которые также используют параметры первичного конструктора в новый конструктор.

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

Ответ 2

(\{\s*)(\w*\s*?=\s*?\w*\s*?;\s*?)*?(public\s*\w*\s*)(\w*)(\s*?{\s*?get;\s*?\})(\s*?=\s*?\w*;\s*)
\1\2\4\5

Несколько ответов: первый с простым поиском и заменой Regex, который нужно повторить несколько раз:

  1. Регулярное выражение: несколько строк объяснения, а затем фактическая строка регулярного выражения и строка замены:

    а. В регулярном выражении сначала вы выбираете полную строку того, что ищете (в вашем случае основной конструктор). Нетрудно сделать: поиск фигурных скобок, слово public, затем два слова, знак равенства и т.д. Каждый найденный в соответствии с этим текст называется Match.

    б. Иногда в тексте возможны повторяющиеся последовательности, которые вы ищете. (В вашем случае: параметры определены в строке для каждого). Для этого вы просто помечаете ожидаемую последовательность как Группу, заключая ее в круглые скобки.

    с. Затем вы хотите пометить разные части найденного, чтобы вы могли использовать их или заменить в исправленном тексте. Эти части также называются "Группы", на самом деле "Группы захвата". Снова просто окружите части круглыми скобками. В вашем случае вы сохраните первую захваченную группу (фигурную скобку) и имя свойства с его назначением параметру.

    д. Здесь регулярное выражение:

    (\{\s*)(\w*\s*?=\s*?\w*\s*?;\s*?)*?(public\s*\w*\s*)(\w*)(\s*?{\s*?get;\s*?})(\s*?=\s*?\w*;\s*)
    
    1. ( 
          // ---- Capture1 -----
          {         
              // code: \{\s*? 
              // explained: curley bracket followed by possible whitespace
       ) 
    
    2. ( - Capture2  - previously corrected text 
          // - possible multiple lines of 'corrected' non-primary-constructors 
          // created during the find-replace process previously, 
    
          Propname = paramname;  // word,  equals-sign, word, semicolon 
          // code:  \w*\s*?=\s*?\w*\s*?;\s*?
          // explained:   \w - any alphanumeric, \s - any whitespace
          //              * - one or more times, *? - 0 or more times 
       )*?  
          // code: )*?
          // explained:  this group can be repeated zero or more times 
          // in other words it may not be found at all. 
          // These text lines are created during the recursive replacement process...
    
    3. ( 
          //  ----Capture 3-----
          // The first line of a primary constructor: 
          public type
          // code: public\s*\w*\s*  
          // explained: the word 'public' and then another word (and [whitespace]) 
        )
    
    4. (
        // ----- capture 4 -----
        Propname
         // code: \[email protected]  
         // explained:  any amount of alphanumeric letters
       )
    
    5. (
         // ---- capture 5 ----
         { get; }
         // code: \s*?{\s*?get;\s*?\}
       )
    
    6. (
        // ---- capture 6 ----
         = propname; 
        code: \s*?=\s*?\w*;\s*
        explained: by now you should get it. 
    

Строка замены

\1\2\4\6

Это оставляет:

{ 
    [old corrected code] 
    [new corrected line]
    possible remaining lines to be corrected. 
  1. Notepad++ 10 минут проб и ошибок. Я гарантирую, это не займет у вас больше, чем это.

  2. Visual Studio 2014 рефакторинг. но а. Вы должны установить его на отдельную виртуальную машину или компьютер. MS предупреждает вас не устанавливать его рядом с существующим кодом. б. Я не уверен, что рефакторинг работает по-другому. [Here an article about it][1]

  3. Макросы Visual Studio. Я знаю, я знаю, они давно ушли, но есть как минимум два плагина, которые заменяют их и, возможно, больше. Я читал о них в этой SO (Qaru) дискуссии. (Они дают несколько других вариантов) Здесь:

  4. Visual Commander - бесплатное дополнение для запуска макросов Visual Studio с открытым исходным кодом
  5. VSScript - надстройка Visual Studio: стоит $ 50 !!

  6. Попробуйте Автоматическое регулярное выражение на примере: вы даете ему несколько примеров кода, в котором вы выделяете то, что является ожидаемым результatom, а затем тот же (или другой) код, в котором вы выделяете то, что НЕ является ожидаемым результatom. Затем вы ждете, пока он пройдет через примеры, и дадите вам некоторый код регулярного выражения.

    //для следующего кода (из http://odetocode.com/blogs/scott/archive/2014/08/14/c-6-0-features-part-ii-primary-constructors.aspx)

    публичная структура Money (строковая валюта, десятичная сумма) {   public string Currency {get; } = валюта;   общедоступная десятичная сумма {get; } = сумма; } // Я получаю что-то вроде: {++\w\w [^ r-u] [^ _] ++ | [^ {] ++ (? = {\ w++ =)

  7. Играйте с регулярным выражением на этом замечательном сайте: https://www.regex101.com/

    // I first tried: \{\s*((public\s*\w*\s*)\w*(\s*?{\s*?get;\s*?})\s*?=\s*?\w*;\s*)*\}
    

Повторяющаяся последовательность строк первичного конструктора ("группа повторного захвата") захватывает только последнюю.

  1. Используйте код c # с regex.captures, как описано здесь, в другом Кару (см. принятый ответ)