ААА! Пришло время переписывать на .NET Coreǃ

Все мы давно хотим перелезть на .NET Core, но постоянно что-то мешает. Например, ничего не поделаешь, когда не хватает важных API. В версии 2.0 процесс упростили благодаря .NET Standard 2.0, но это ещё не всё. Ну что ж, Microsoft-боги вняли нашим молитвам и завезли 20 000 API, доступных в виде одного-единственного пакета в NuGet!


7t7ynubqjfykixuoaebywicsmdo.png


Кому это вообще нужно?

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


Скептикам же надо как бы напомнить, что .NET Core пилится специально для масштабируемых веб-приложений на всех разумных операционных системах (GNU/Linux, macOS и Windows), а более точно выбрать между Core и Framework поможет специальный документ.


Как это использовать?

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


Предположим, вы накодили приложуху на ASP.NET MVC для Windows-локалхоста, и вас за это не уволили. Настало время перетащить ее на правоверный Linux, работающий на Azure! Лучше есть слона по кусочкам, а именно:


  • Перетащить всё на ASP.NET Core (но целевой платформой продолжать держать .NET Framework);
  • Переползти на .NET Core (но продолжать юзать Windows);
  • Перепрыгнуть на GNU/Linux;
  • Запуститься на Azure.


Понятно, что к этому великому плану стоит подходить не как к строительству коммунизма, а разумно. Например, если нужно показать биг боссам запуск на Azure — с этого и стоит начать. Если же думать лень (мне, например, точно лень), наши лидеры написали специальную методичку по обретению веры в .NET Core.


Вкратце, нужно расчехлить NuGet, поставить пакет Microsoft.Windows.Compatibility и обнаружить, что стала доступна огромная куча разных нужных и ненужных API.


Важно понимать, что этот самый Microsoft.Windows.Compatibility всё еще яростно допиливается, так что все офигительные истории нам только предстоят.


Сейчас имеется следующий набор ништяков (таблица получилась огромная; чувак, читающий этот пост с мобилы: прости меня пожалуйста!):


Компонент Статус Windows-Only
Microsoft.Win32.Registry Available Yes
Microsoft.Win32.Registry.AccessControl Available Yes
System.CodeDom Available
System.ComponentModel.Composition Coming
System.Configuration.ConfigurationManager Available
System.Data.DatasetExtensions Coming
System.Data.Odbc Coming
System.Data.SqlClient Available
System.Diagnostics.EventLog Coming Yes
System.Diagnostics.PerformanceCounter Coming Yes
System.DirectoryServices Coming Yes
System.DirectoryServices.AccountManagement Coming Yes
System.DirectoryServices.Protocols Coming
System.Drawing Coming
System.Drawing.Common Available
System.IO.FileSystem.AccessControl Available Yes
System.IO.Packaging Available
System.IO.Pipes.AccessControl Available Yes
System.IO.Ports Available Yes
System.Management Coming Yes
System.Runtime.Caching Coming
System.Security.AccessControl Available Yes
System.Security.Cryptography.Cng Available Yes
System.Security.Cryptography.Pkcs Available Yes
System.Security.Cryptography.ProtectedData Available Yes
System.Security.Cryptography.Xml Available Yes
System.Security.Permissions Available
System.Security.Principal.Windows Available Yes
System.ServiceModel.Duplex Available
System.ServiceModel.Http Available
System.ServiceModel.NetTcp Available
System.ServiceModel.Primitives Available
System.ServiceModel.Security Available
System.ServiceModel.Syndication Coming
System.ServiceProcess.ServiceBase Coming Yes
System.ServiceProcess.ServiceController Available Yes
System.Text.Encoding.CodePages Available Yes
System.Threading.AccessControl Available Yes


А что делать с Windows-only API?

Страдать, чо.

Для танкистов. Не все API одинаково переносимы. Если ты остаешься на Windows, проблем никаких нет. Если же хочешь приобщиться к святости Ричарда Столлмана и Тима Кука на GNU/Linux и macOS соответственно, придется страдать.


Взглянув на табличку ништяков, видим: Windows-only компонентов там чуть ли не половина. Добрые Microsoft-боги, тем не менее, позволяют успешно компилировать такой код под любой платформой. При попытке использования несуществующей фичи мы наткнемся на PlatformNotSupportedException в рантайме, поэтому все такие фичи нужно будет густо обмазать вызовами RuntimeInformation.IsOSPlatform():


private static string GetLoggingPath()
{
    // Verify the code is running on Windows.
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Fabrikam\AssetManagement"))
        {
            if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
                return configuredPath;
        }
    }

    // This is either not running on Windows or no logging path was configured,
    // so just use the path for non-roaming user-specific data files.
    var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    return Path.Combine(appDataPath, "Fabrikam", "AssetManagement", "Logging");
}


Как же понять, какая API-шка будет работать только в Windows? Документацию ведь никто не читает, верно?


Дорогой мой любитель программирования копипастой со StackOverflow! Microsoft — боги суровые, но справедливые, поэтому буквально пару недель назад они запилили API Analyzer tool. С помощью Roslyn эта тула помечает Windows-only API, причем только тогда, когда целью выставлен .NET Core или .NET Standard.


o2ny5b9d-zvw7_tp9h6phn5qds4.png


Что делать с ошибками? Как было сказано ранее, страдать.


  • Удалять непортируемый код. Зачем нужна фича, если она не запускается на macOS? :-)
  • Усердно рефакторить код с помощью других, более кроссплатформенных API. Благо это обновление принесло таких во множестве.
  • Расставить проверки на тип операционки в тех местах, где происходят GNU/Linux-специфичные вещи, которые просто не нужны в Windows.


В примере с картинки кто-то пытается вычитать настроечку в Реестре. Можно обернуть эту строчку в проверку, выполнять ее только на Windows. В GNU/Linux эквивалент этой строчки будет другим, куда более мучительным.


Заметьте, что Windows Compatibility Pack — это метапакет. В Microsoft отлично понимали, что обычные люди не будут мучиться с выискиванием отдельных мелких пакетиков и захотят перейти на новую платформу одним прыжком (с учетом оговорок выше). Тем не менее, если ты — вдумчивый крутой разработчик, то можно притаскивать фичи и поодиночке. Таким образом, можно будет выкинуть куда больше зависимостей на ненужный хлам.


Что дальше?

Морально готовишься к портированию. Устанавливаешь Windows Compatibility Pack. Изучаешь ништяки, коих там более 20 тысяч, включая EventLog, WMI, Performance Counters, Windows Services итп.


Если хочешь сделать приложуху кроссплатформенной — запускаешь API Analyzer. Можно предварительно немного поплакать или тяпнуть водочки.


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

© Habrahabr.ru