Все мы давно хотим перелезть на .NET Core, но постоянно что-то мешает. Например, ничего не поделаешь, когда не хватает важных API. В версии 2.0 процесс упростили благодаря .NET Standard 2.0, но это ещё не всё. Ну что ж, Microsoft-боги вняли нашим молитвам и завезли 20 000 API, доступных в виде одного-единственного пакета в NuGet!
Кому это вообще нужно?
Вкратце, это нужно всем. Имхо, сама возможность перетащить свои тонны легаси на .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.
Что делать с ошибками? Как было сказано ранее, страдать.
- Удалять непортируемый код. Зачем нужна фича, если она не запускается на 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 не покрывает нужды десктопной разработки. Возможно, когда-нибудь это изменится. Но это уже совсем другая история.
Если же хочется больше узнать о .NET вообще и .NET Core в частности, ждем тебя на DotNext 2018 Piter, которая пройдет, внезапно, в Питере. Очень советую к этой конфе уже попробовать что-нибудь запилить или портировать на Core, чтобы накопился пул вопросов к спикерам.
Комментарии (54)
olku
20.12.2017 13:52+1Мы перепрыгнули уже довольно давно, полет нормальный. Кластер из нескольких Коровских нод на Никсах за Хапрокси и последовательный деплой без даунтайма — берем лучшее из обоих миров.
Bradseet
21.12.2017 12:35+1Можете немного подробнее рассказать как все работает? Хотим у себя сделать нечто подобное, но пока только в начале пути. Например, чем деплой делаете?
olku
21.12.2017 13:40Ansible. Но это не принципиально. Можно шелл-скриптом из репозитория раскатывать, если нод немного. Деплой в новую папку, стоп старой, старт новой версии. Откат еще быстрее. Если ХА не нужен, можно оставить Кастрюлю, смотрящей в сеть, как есть. Делали нагрузочные на Никсах, она параллельно летает. Асинк-авейт, все такое. Нгинкс как прокси перед Кастрюлей показался избыточным. Но то дело вкуса.
RomanPokrovskij
20.12.2017 13:57+1Непонятно. System.Data.SqlClient доступен был с незапамятных времен, отдельным пакетом. Если Microsoft.Windows.Compatibility можно ставить по частям, то так и надо написать.
RomanPokrovskij
20.12.2017 14:04+1Не только «десктопные приложения» неподдерживаются…
System.Diagnostics.PerformanceCounter и System.DirectoryServices только только стали доступны как preview1 (в вашей таблице Coming это и означает). т.е. портировать серверный код (где без данных библиотек не обходится) — удел одиночек. Писать новые проекты — конечно надо под core, осваивая новую МС телеметрию и вынося адапетр к ActiveDirectory в отдельный удаленный сервис, который будет крутится под Classic .NET Framework.olegchir Автор
20.12.2017 14:17Ну тут такое, release early, release often, как говорил батюшка наш Эрик Реймонд. Наверное, раз уж подписался на участие опенсорце, придется жить по опенсорцным заповедям: постоянно сидеть на превьюхах, мониторить новости, адоптить частые апдейты. И главное, справляться своими силами, а не ждать, пока добрый дяденька из Microsoft тебе всё запилит.
RomanPokrovskij
20.12.2017 14:35+1Да, наверное есть о чем поговорить друг с другом любителям посидеть на превьюхах ядра линукса.
blanabrother
20.12.2017 15:11+1К сожалению, сейчас .NET Core не покрывает нужды десктопной разработки. Возможно, когда-нибудь это изменится. Но это уже совсем другая история.
.NET Core, как и старший .NET Framework, умеет в DllImport, маршалинг между managed и unmanaged. Т.е. платформа как исполнитель управляемого кода и интегратор с неуправляемым ОС-специфичным кодом как раз все позволяет и покрывает. Поэтому правильнее говорить, что нынешний набор пакетов не покрывает все нужды десктопной разработки.
unsafePtr
20.12.2017 15:16Всё равно осадочек остался от того что протащили windows-only API. Лучше совсем без них, и для windows-a предоставлять их в виде отдельных nuget пакетов. В принципе это ещё не поздно исправить, но никто этим заниматься не будет. Сейчас у них цель, проапгредить и заоптимизировать сетевой стек.
casperonius
20.12.2017 15:40Настало время перетащить ее на правоверный Linux, работающий на Azure!
Один я вижу в этих словах противоречие? =)
Sovetnikov
20.12.2017 17:46+1А зачем мы давно хотим перелезть на .NET Core?
Sioln
21.12.2017 10:36Тот же вопрос. Вот есть у меня зоопарк (теперь типа legacy) приложений на .NET 4.Х. Худо-бедно работает и мы трудимся над расширением функционала.
Тут вышел .NET Core, и мы должны переписывать? Чего ради? Для повышения производительности? Для большей переносимости?
Не уверен, т.к. в моей компании это не принесет денег. А устранение косяков и расширение функционала — принесет.
kovserg
20.12.2017 21:23+1Надо было сразу на PHP, Java или Go писать что бы потом не ползать по .net core-ам.
Да и зачем всё переписывать если есть виртуальные машины с образами систем готовых систем, которые разворачиваются по мере необходимости. И так работает зачем еще переплачивать?Free_ze
20.12.2017 23:32И так работает зачем еще переплачивать?
Как я понял, в статье речь о том, что это стало практически бесплатно. Без виртуальных машин и прочего инструментального оверинжиниринга.kovserg
22.12.2017 09:41Посмотрите на современный софт, оверинжиниринг никого не пугает. Да же наоборот, притягивает. Контейнеры, виртуальные машины, облака. Зачем переписывать побольше инстансов оплатил и вперёд. Труд программистов дорог, а вычислительных мощностей хоть ж… ой ещь и не дорого.
Free_ze
22.12.2017 10:25В современности много бестолковых специалистов, которые готовы технологиями (и ресурсами для них) покрывать свою безграмотность. Безусловно, их такие возможности радуют.
Виртуализация — отличная вещь там, где она нужна. В любую дырку толкать докер лишь потому, что это мейнстримово — это очевидная глупость, за которую платит бизнес.
Зачем переписывать
Не нужно ничего переписывать, о том и статья.Sioln
22.12.2017 10:59Странно, а в заголовке «переписывать».
И по факту, чтобы приложение было .NET, а стало Core — его придётся переписывать. Да, какую-то часть кодовой базы можно использовать повторно.Free_ze
22.12.2017 11:23Странно, а в заголовке «переписывать».
Забавно, но в тексте статьи этого нет. Все эпитеты про «перетащить» подразумевают запуск в новом окружении. Пакет призван обеспечить слой совместимости на уровне исходников.
И по факту, чтобы приложение было .NET, а стало Core — его придётся переписывать.
Это совсем не факт, ибо сильно зависит от самого приложения и состояния сабжект-пакета.
Frank59
22.12.2017 11:28+1Если кто-то питает иллюзии, что ничего не придется переписывать — стоит перестать это делать.
Из того, на что напарывались:
— Nhibernate -> Dapper
— Ninject -> стандартный DI
— log4net заводится через одно место
— полностью новая инициализация сервиса(на Net 4.6 был OWIN + Topshelf)
— завести NUnit на TeamCity нифига не просто и тащит за собой обновление TeamCity
— переписать билд-скрипты на dotnet build|publishmayorovp
22.12.2017 11:34Почти все что вы перечислили можно описать одним словом: сторонние библиотеки/продукты.
Да, если сторонний продукт который вы используете не поддерживает Core — вы не сможете без переписывания работающего с ним кода переехать на Core. Это очевидно же…
PS так вернули же msbuild в core, разве нет?
Free_ze
22.12.2017 11:37Ninject -> стандартный DI
Актуальный (стабильный) Ninject умеет в .NET Standard 2.0
kefirr
21.12.2017 10:24Стоит упомянуть, что из проектов на .NET Core 2.0+ можно референсить сборки и нугеты ЛЮБОЙ версии .NET, и оно будет работать под линух, если либа не использует windows-specific API.
То есть если вы — автор библиотеки, то не обязательно переезжать на кору, достаточно проверить, что нет windows-specific вызовов, или обернуть их в if-else.
Мы так поступили в Apache Ignite.NET. Всё работает под линух и макось, но сохранена поддержка VS 2010.
Terras
21.12.2017 12:26К чему Microsoft идет в итоге?
Делает Кросс-платформенный фреймворк + отдельно фреймворк для винды. Или все же сделает один адекватный фреймворк подо все + отдельный пакет для лучшей интеграции с виндой?vyatsek
21.12.2017 13:00+1Сделать кросс платформенный NET Core это реально хорошая идея и в какой-то степени может потеснить Java на nix платформе.
Terras
21.12.2017 16:551) Сделать полную поддержку на Linux — тогда Java подвинется, так как зачастую именно цена хостинга + лицензий (отпугивает стартапы) + отсутствие тулзов линукса отпугивает крупные проекты.
2) Сделать Gui-инструмент для Linux/MAC — тогда уже подвинутся все остальные.Simplevolk
21.12.2017 17:05+1Радуюсь появлению .net core, все свои пет проекты пишу на нем, под VS 2017 и Win10, а запускаю их на simplecloud на 150р тарифе под Ubuntu.
Мне как раз подходит на 100%.
vyatsek
22.12.2017 13:151) Сделать полную поддержку на Linux — тогда Java подвинется, так как зачастую именно цена хостинга + лицензий (отпугивает стартапы) + отсутствие тулзов линукса отпугивает крупные проекты.
Так или иначе движ есть. MS раньше позиционировалась как вещь в себе, типа нафиг эти ваши линуксы, у нас есть все(сервер, базы, серверные приложения) и мы крутые. Но мир поменялся, линукс плотно осел на сервер сайде и MS долю серверного рынка на Linux полностью потеряла. Потом они начали пытаться «запрыгнуть в уходящий вагон» и начали накручивать всякую совместимость(она правда и до этого была, но кто ей пользовался хз) с Linux, en.wikipedia.org/wiki/Windows_Subsystem_for_Linux.
Про последнее я тоже не думаю что это прям взлетит. Общие кейсы в голову не приходят, а какие-то узкоспециализированные интереса не представляют.
А вот .NET это несколько другое общий и обширный вариант использования это ASP.NET да и да и просто серверные .NET приложения. И вот с этим крюком MS может залезть в Linux вагон.
Это не говорит о том, что все ринутся переписывать. Но при выборе платформы для нового приложения решение может склониться в сторону .NET on Linux
Shrike
21.12.2017 13:26я извиняюсь, но имело смысл указать, что это перевод поста Иммо — blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core
olegchir Автор
22.12.2017 23:31+1Ссылка же на оригинал новости есть прямо в первом абзаце (и она была там всегда, до этого комментария).
Но это не перевод, а рерайт. Несмотря на в общем похожую структуру, есть важная разница в ряде моментов: например, я утверждаю что на .Net Core переходить нужно в любом случае просто потому что это Free Software, и мне как FS/OSS-человеку это самое важное. Я супер редко пользуюсь какими-либо продуктами Microsoft именно потому, что это не Free Software, неважно насколько качественными или полезными они при этом являются. Но это совершенно не годится на официальную позицию Microsoft.
На «официальную позицию» не годится так же идея о том, что текущий подход к портированию — неудобный, и людям которые хотят что-то портировать — им остается только страдать. На официальную позицию не тянет троекратное упоминания подозрения, что половина читающих эту статью — те еще быдлокодеры и копипастеры со StackOverflow.
В принципе, мне ставить галочку «перевод» даже выгодно. Но вряд ли Microsoft обрадывалось бы двачерским словечкам и оборотам, которые приписали бы им словом «перевод» в заголовке. Это важный для меня момент, т.к. я не собираюсь ни отказываться от двачерской лексики, ни от глумёжа и обвинений в быдлокодерстве, итп — это мой стиль. Но при этом не хочу иметь официальные конфликты с Microsoft.
Я думаю, так или иначе, большинство новостей в мире фреймворков вторичны, и новости будут так или иначе идти от корневых источников — мейлинг-листов и сайтов авторов. Так что в дальнейшем рерайты новостей я писать продолжу. Вряд ли стоит выражать вторичность новости в виде галки «перевод».
Какие выводы я сделал из вашего комментария: в будущем нужно будет делать более глубокую проработку новости и менять её структуру, чтобы она не была «переводом» на уровне структурных блоков (или хотя бы — порядка структурных блоков).
Frank59
21.12.2017 15:55Переезжать серверным системам стоит если:
а) вы видите профит от снижения затрат на хостинг за счет перехода на линукс
б) у вас (микро)сервисы и вы понимаете зачем вам докер
в) ваш заказчик купил линукс сервера, не посоветовашись с вами
Новые проекты имхо стоит все-таки начинать сразу под netstandard2.0 или вообще на java от греха подальше=)
focuspocus
22.12.2017 23:21+2Был angularjs/webapi2/signalr + workerservice проект с EF 6 на postgresql, который надо было перетянуть под linux.
Из граблей в основном грабли от ms, сторонние либы на удивление быстро и без особого изменения поведения/конфигурации перескочили (autofac, automapper, hangfire, npgsql и тд):
1) EF 6 -> EF Core 2.0: нет groupby (уже в гите); нет lazy loading(больше года делают и в лучшем случае в начале 2018); с хранимками и маппингом функций бывают траблы; многие ко многим только через промежуточную сущность(но обещают сделать как и былО).
2) Ldap: Не из коробки. два года обсуждали, сделали пока только под винду github.com/dotnet/corefx/issues/2089, но есть различные форки новеловской либы.
3) WebApi 2 -> aspnet core 2: Были забавные случаи с байндингом, где не стоял явный [FromBody]: приходили объекты с пустыми полями, документация по переезду про это мало знает, люди мутят гибридные байндеры. Пришлось подразбираться с конфигурацией приложения при запуске, с конфигурацией (ConfigurationManager появился только с этим пакетом), контейнеров, воткнуться в пайп(чтобы ловить исключения).
4) Signalr: относительно недавно появился preview. Немного доделок и все заработало.
5) Были грабли с определением рабочего каталога при запуске с отладкой и без (фикс только сегодня за пулреквестили)
6) решарпер со студией пару раз зареференсили либу вместо nuget пакета, нужно следить.
7) отказались от tika.net потому, что автор ikvm.net забил весной на проект и переезда не будет.
Итого: самая большая боль — EF CoreRomanPokrovskij
23.12.2017 13:15Вопрос в сторону, поделитесь опытом, а почему вы предпочли оставить autofac когда в Core DI из коробки (который я не использую, правда я ни один стандартный IoC container не использую поскольку мне нужна поддержка экземпляров «per session» и решается это как раз отказом от IoC container'ов и ручным DI)?
focuspocus
23.12.2017 14:29В освновном из-за конфигурации и некоторых возможностей, а также лимита времени(и
немного лени). Конфигурация DI переехала вообще без изменений. В проекте не использовался скан сборок с автоматической конфигурацией. Был сайт, фоновый сервис и несколько сервисных утилит. В каждой программе свой набор компонент и свой конфиг.
У нас часто используется Lazy<>, чтобы вещи, которые не всегда используются в сервисе, не создавались каждый раз. Насколько я помню, в дефолтном контейнере забраковали open generics. К тому же есть пара мест с child контейнерами (этой фичи тоже нет стандартном). Еще было бы лениво заменять в конструкторах ILogger на ILogger, у нас уже был модуль для autofac, который делал черную магию, зная о типе, куда будет инжектироваться параметр.focuspocus
23.12.2017 14:56Извиняюсь! Перечитал уже после отправки. Выпало важное слово! «забраковали constrained open generics». Даже нашел подробности github.com/aspnet/DependencyInjection/issues/471
И бонусом про Lazy github.com/aspnet/DependencyInjection/issues/98
yarosroman
Про десктоп, проект AvaloniaUI. Базируется на XAML. Ну ещё и не релиз пока, но можно уже много интересного делать.
olegchir Автор
О, расскажи про Авалонию. Ты уже что-нибудь пробовал сделать? Что показалось наиболе интересным, чудесным и вообще труЪшным? Какие грабли собрал?
unsafePtr
ARG89 указал кого надог звать, ну я оставлю замечательную презентацию с прошлого dotnext отkekekeks
yarosroman
Ну до WPF пока не дотягивает. Но слова были, что остаётся только мечтать о десктопе на net.core, но уже есть проект, на котором уже можно делать вещи. И это радует.
yarosroman
О, интересно читать комментарии официального представителя, который отвечает как быдло последнее.
olegchir Автор
Чего? Короче, даже знать не хочу, где я тебе ответил как быдло. Просто пойми, я из Новосиба, с Богдашки, мы с Васей-Молотом ещё в школе столько конкурентов по .NET-аутсорсу в тайге закопали, а тогда и .NET ещё не было. Накладывает отпечаток на стиль изложения.
ARG89
Зовите kekekeks, он расскажет)
kekekeks
А что рассказывать, на дотнексте я уже по этому поводу вещал. Ждите релиза беты в начале года.
arxont
А датагрид в бете будет?
kekekeks
Нет. У вас всё ещё сохраняется уникальный шанс стать тем самым человеком, который перепишет все 50К+ строк кода опенсорсного грида из состава сильверлайта. Или 125К строк кода Xceed-овского грида.