Posted on 1. May 2023

Малювання елементів на картах за допомогою .NET MAUI

 

 

Чи знаєте ви, що .NET MAUI має повний контроль Map над програмами iOS, Android і MacCatalyst? Він з’явився разом із запуском .NET 7 і дозволяє не лише відображати карту зі шпильками, але також дозволяє повноцінно малювати багатокутники, полілінії та кола! Давайте сьогодні подивимося на елементи керування Map, як відображати позначки, як малювати контури та пішохідні доріжки в кампусі Microsoft у Редмонді!

Позначки на карті

 

Елементи керування Map в .NET MAUI пропонують широкий спектр налаштувань відображення карти. Одним із основних елементів, які люди розміщують на карті, є маркер Pin із текстом. Властивість елемента Pins контролера Map це властивість IList, яку ми можемо заповнювати динамічно, щоб поставити якомога більше позначок на карті. Це можна зробити в XAML:

Ви можете вказати позначки безпосередньо в XAML або використати прив’язку даних до списку Pin, за допомогою властивості  ItemsSource подібної до ListView або CollectionView.

 

Ви також можете зробити це безпосередньо в коді C#:

Ще краще, ви можете додавати події до Pin, щоб побачити, коли його клацнули або коли клацнули інформаційне вікно за допомогою подій MarkerClickedі InfoWindowClicked на Pin.

Нанесення елементів на карту

А тепер давайте розважимося і намалюємо кілька ліній і багатокутників на карті! Властивість MapElements у Map містить список MapElement, список елементів які можна намалювати на карті. У .NET MAUI вбудовано три елементи:

- Коло : коло, проведене з центральної точки із заданим радіусом

- Багатокутник : повністю закрита форма. Перша й остання точки з’єднуються автоматично.

- Ламана лінія : низка точок, з’єднаних накресленими лініями

За допомогою цих трьох елементів ви можете робити на карті майже все! Наприклад намалювати над кампусом Microsoft у Редмонді лінію, що показує доріжку між східним і західним кампусом:

 

Спочатку намалюймо два елементи Polygon, які представляють наш Західний і Східний кампус. Кожен із них візьме список об’єктів Location у властивості Geopath, які визначатимуть точки контуру. Polygon автоматично з’єднає кожну з цих точок із Stroke повним фоном, який ви можете визначити, за допомогою FillColor. Усе це можна створити безпосередньо в XAML без зв’язування даних або безпосередньо в C#, як мені більше подобається під час роботи з картами.

Оскільки наші два регіони Polygon визначені зараз, все, що нам потрібно зробити, це створити Polyline як міст, який з’єднує дві частини кампусу. Polyline дуже схожий на Polygon, але він автоматично не «з’єднує» початкову та кінцеву точки, і немає фонової заливки. Це просто точки на карті, з’єднані лінією.

Тепер настав час завантажити ці елементи до нашого контролера Map у властивість MapElements та, звичайно, збільшити масштаб карти до позиції над кампусом:

 

Ось воно! Наша карта тепер повністю відображає наші два регіони та лінію, яка представляє доріжку мосту між кампусом! Ви завжди можете додати та видалити стільки MapElement, скільки завгодно!

Вивчайте більше

Ще багато чого можна дізнатися про контролер Map! Нещодавно я зняв коротке оглядове відео, яке наполегливо рекомендую переглянути.

Source



Posted on 30. April 2023

Анонсуємо .NET Community Toolkit 8.2! Покращена швидкість роботи генераторів, засоби для усунення помилок у коді, збільшення продуктивності та багато іншого!

 

 

Ми раді повідомити про офіційний запуск версії 8.2 інструментарію .NET Community Toolkit! Ця нова версія містить покращення швидкості роботи як під час виконання, так і в генераторах вихідного коду MVVM Toolkit, нові засоби для усунення помилок, що підвищують вашу результативність, нові функції на основі запитів користувачів та багато іншого!

.NET Community Toolkit 8.1.0 Preview 1

Що входить до інструментарію .NET Community Toolkit? 👀

Інструментарій .NET Community Toolkit містить наступні бібліотеки:

  • CommunityToolkit.Common

  • CommunityToolkit.Mvvm (також відомий як “Microsoft MVVM Toolkit”)

  • CommunityToolkit.Diagnostics

  • CommunityToolkit.HighPerformance

Ці компоненти також широко використовуються в деяких програмах для роботи з вхідними повідомленнями, які постачаються з Windows, зокрема у Microsoft Store і програма “Photos”! 🚀

Для більш детальної інформації про історію розвитку інструментарію .NET Community Toolkit, ось посилання на попередній пост з анонсом версії 8.0.0.

 

Перелік основних змін, які включені в нову версію 8.2 інструментарію .NET Community Toolkit.

Користувацькі атрибути для [RelayCommand] 🤖

Продовжуючи роботу, виконану у випуску 8.1.0, і як було запропоновано на GitHub, новий випуск 8.2.0 набору інструментів MVVM Toolkit містить підтримку користувацьких атрибутів при використанні [RelayCommand]. Знову ж таки, було використано нативне field: і property: C#, щоб вказати цільові значення користувацьких атрибутів. Завдяки цьому ви тепер маєте повний контроль над атрибутами для всіх згенерованих членів, коли використовуєте [RelayCommand] для створення команди MVVM.

Наприклад, це особливо корисно, коли ви використовуєте модель подання, яка має підтримувати серіалізацію JSON, і вам потрібно явно ігнорувати згенеровану властивість. Ви можете використовувати підтримку нового  field: і property: наступним чином:

Після цього будуть створені наступні елементи:

Як і слід було очікувати, згенерована властивість DoWorkCommand має вказаний атрибут над нею! І, звичайно ж, підтримуються атрибути з будь-якою кількістю конструкторів та іменованих параметрів. Ви також можете використовувати просто field:, property:  поле:або будь-яку їх комбінацію 🙌

Ви можете знайти всі документи про нові генератори вихідних кодів тут, а якщо ви віддаєте перевагу відеоверсії, Джеймс Монтемагно також зробив кілька відео про них, наприклад, це.

Нові змінені перехоплення [ObservableProperty] ⚗️

Відносно поширеним сценарієм у MVVM є наявність деякої властивості “вибраний елемент”, яка представляє, наприклад, поточного вибраного користувача або вкладену модель представлення. Коли значення цієї властивості змінюється, нерідко доводиться вносити певні корективи до старого та нового екземплярів. Наприклад, встановити якусь “вибрану” властивість, або підписатися на подію, і так далі.

Раніше це був сценарій, де використання [ObservableProperty] не було ідеальним, оскільки воно не мало необхідної інфраструктури, щоб легко впровадити таку логіку для виконання необхідних змін стану для старих і нових значень, що встановлюються. Щоб виправити це, починаючи з версії 8.2 MVVM Toolkit, для всіх полів [ObservableProperty] генеруються два нові змінені перехоплення властивостей.

 

Наприклад, розглянемо наступний код:

Тепер буде згенеровано такий код:

Зверніть увагу на два нові методи “OnPropertyNameChanging” і “Changed”, що генеруються, тепер вони також приймають попереднє значення. Ці два методи є простими у використанні перехопленнями для додавання коду, який спрацьовує при кожній події зміни властивості й може змінювати як старе, так і нове значення, що встановлюється. Наприклад, ви можете використовувати їх наступним чином:

І це все, що вам потрібно! Вибрана модель перегляду тепер завжди буде коректно повідомлятися як вибрана. Вам більше не потрібно повертатися до використання ручної властивості у подібних сценаріях, [ObservableProperty] тепер має вбудовану підтримку і для цього! 🪄

Примітка: MVVM Toolkit автоматично визначить, чи використовуєте ви будь-який з цих методів, щоб максимально оптимізувати кодову структуру. Крім того, виклики методів, які не реалізовані, будуть просто видалені компілятором Roslyn, тому вся ця функція є повністю платною!

Фіксери коду MVVM Toolkit 📖

У попередньому випуску MVVM Toolkit було додано два нових діагностичних аналізатора, які видають попередження при некоректному доступі до поля, позначеного [ObservableProperty], а також при оголошенні типу з [ObservableProperty] і подібними атрибутами, коли доступне використання наслідування. У версії 8.2 ці два аналізатори також містять вбудовані засоби для виправлення коду!

Тобто, коли будь-який з них видає попередження, ви можете просто навести курсор на лампочку IntelliSense, вибрати виправлення коду й автоматично застосувати всі необхідні зміни, щоб повернути ваш код до правильного вигляду! Вони також підтримують групові виправлення, тому ви можете виправити всі помилки одним клацанням! ✨

MVVM Toolkit analyzer code fix

Тут ви можете побачити новий інтерфейс виправлення коду у Visual Studio з попереднім переглядом змін, а також опціями застосування виправлення до потрібного вам діапазону

Оптимізація генератора вихідного коду MVVM Toolkit 🛫

Як і кожен випуск, MVVM Toolkit 8.2 також включає деякі покращення продуктивності генераторів вихідних кодів. Цього разу основна увага була приділена оптимізації інкрементних конвеєрів, щоб мінімізувати використання пам’яті й гарантувати, що жодні непотрібні об’єкти не залишаться активними під час паралельних виконань. Ось деякі зміни, які було зроблено для покращення цього:

  • Перенесено решту діагностик до аналізаторів (#581): ще дві діагностики з MVVM Toolkit було перенесено до діагностичного аналізатора, який можна запускати паралельно та поза процесом. Це вилучає деякі символи Roslyn з інкрементального конвеєра та покращує загальну продуктивність генератора.

  • Попередня обробка символів на початку роботи аналізаторів (#587): усі необхідні символи аналізатора тепер обробляються під час початкового налаштування зворотного виклику, що пришвидшує його виконання у кожному екземплярі компіляції.

Інші зміни та покращення 🚀

  • Виправлено помилку збірки з VB.NET проєктів (#592): MVVM Toolkit спричиняв помилки збірки з VB.NET проєктів через деякі некоректні властивості MSBuild. Наразі це виправлено.

  • Виправлено перенаправлені параметри подвійних атрибутів (#603): перенаправлені атрибути через [ObservableProperty] некоректно відображали цілі значення типів float та double у тип int. Тепер вони передаватимуться коректно зі збереженням початкового типу.

  • Виправлено генератори вихідного коду, що обробляють вкладені/загальні типи (#606): виправлено проблему, яка призводила до збою декількох генераторів вихідного коду при використанні Roslyn 4.0 та загальних типів.

  • Додано API ArrayPoolBufferWriter.DangerousGetArray() (#616): цей новий API дозволяє легко взаємодіяти між ArrayPoolBufferWriter та старими API, які вимагають масив T[] як параметр (на відміну від Span/Memory).

  • Вилучено System.Linq з CommunityToolkit.Diagnostics (#622): за результатами дослідження, проведеного у runtime/#82607, з пакунка Diagnostics повністю вилучено всі посилання на System.Linq. Це покращує підтримку обрізання у збірці та дозволяє заощаджувати більший розмір двійкових файлів у опублікованих збірках (особливо з NativeAOT).

  • Підтримка часткових методів з [RelayCommand] (#633): атрибут [RelayCommand] тепер працюватиме коректно, якщо його буде додано над визначенням або частиною реалізації часткового методу.

  • Додано підтримку відкритих узагальнених типів у ToTypeString (#639): розширення Type.ToTypeString() тепер коректно обробляє відкриті узагальнені типи. Наприклад, typeof(List<>).ToTypeString() тепер повертатиме “System.Collections.Generic.List<>”.

  • Додано [MemberNotNull] у встановлювачах [ObservableProperty] (#646): коли це застосовано (тобто коли атрибут є доступним і тип властивості не можна занулити), генератор [ObservableProperty] також генеруватиме необхідні анотації про можливість занулення, щоб гарантувати, що встановлення створеної властивості коректно позначить поля як ініціалізовані. Це розв’язує проблему полів, які показували попередження про недопустимість, навіть якщо згенеровану властивість було встановлено.

  • Повні XML-документи для згенерованих членів (#653): усі згенеровані типи та члени тепер оформлено у вигляді повних XML-документів, тож перевірка коду, створеного генераторами вихідного коду MVVM Toolkit, має бути дещо простішою, ніж раніше.

Примітка: у старих версіях Roslyn існує відома проблема з генераторами вихідних кодів, через яку IntelliSense може іноді працювати некоректно для згенерованих елементів (див. #493 і пов’язану з ним проблему відстеження у Roslyn). Ця проблема має бути в основному виправлена в VS 2022 17.6 і вище (або, коли використовується Roslyn 4.6, в тому числі через інші IDE, такі як VS Code і Rider). Якщо ви зіткнулися з цією проблемою, переконайтеся, що ви оновили свій інструментарій до останньої доступної версії.

Інші зміни ⚙️

Ви можете переглянути повний список змін до цього випуску на сторінці релізу на GitHub.

Почніть вже сьогодні! 🎉

Ви можете знайти весь вихідний код у репозиторії GitHub, деякі рукописні документи на MS learn та повні посилання на API на вебсайт браузера .NET API. Якщо ви хочете зробити свій внесок, не соромтеся залишати проблеми або звертатися до команди, щоб повідомити про свій досвід! Щоб стежити за обговоренням у Twitter, використовуйте хештег #CommunityToolkit. Всі ваші відгуки дуже допомагають формувати напрямок розвитку цих бібліотек, тому обов’язково діліться ними!

 

Вдалого кодування! 💻



Posted on 23. January 2023

Анонс .NET Community Toolkit 8.1! Покращені, швидші генератори вихідного коду MVVM, підтримка .NET 7 та багато іншого!



Анонс .NET Community Toolkit 8.1! Покращені, швидші генератори вихідного коду MVVM, підтримка .NET 7 та багато іншого!

З радістю повідомляємо про офіційний запуск версії 8.1 інструментарію .NET Community Toolkit! Ця нова версія містить нові функції, які були дуже запитувані, виправлені помилки та значні покращення продуктивності генераторів вихідного коду MVVM Toolkit, щоб покращити UX для розробників при їх використанні як ніколи!

 

Що входить до складу .NET Community Toolkit? 

Як і в інших анонсах, розпочнемо з невеликого огляду того, що входить до складу інструментарію .NET Community Toolkit. Він складається з декількох незалежних бібліотек:

Ці бібліотеки також широко використовуються у деяких програмах для роботи з поштою, які входять до складу Windows, зокрема у Microsoft Store та програмі “Фотографії”! 

Для більш детальної інформації про історію .NET Community Toolkit, ось посилання на попередній пост з анонсом 8.0.0.

 

Нижче наведено перелік основних змін, які включено до нового випуску 8.1 інструментарію .NET Community Toolkit.

Користувацькі атрибути для [ObservableProperty] (Властивість, що спостерігається) 

Як вже згадувалося у блозі з анонсом 8.1.0 Preview 1, однією з найбільш запитуваних функцій (див. #208, #217, #228) для генератора вихідного коду MVVM Toolkit була підтримка використання користувацьких атрибутів для [ObservableProperty]. Було запропоновано декілька проєктів для підтримки цієї можливості, і зрештою було вирішено використати наявну властивість: синтаксис у C#, який дозволяє розробникам позначати атрибути для поширення їх на згенеровані властивості. Це дає кілька переваг:

1. Він використовує вбудований синтаксис C#, що робить властивість “рідною” і не потребує додаткових атрибутів

2. Це розв’язує проблему анотування атрибутів, які можуть бути спрямовані лише на властивості, а не на поля

 

Тобто, у MVVM Toolkit 8.1 тепер підтримується наступний сценарій:

Це призведе до створення наступної властивості за замовчуванням:

Ви можете побачити, як згенерована властивість має два атрибути, які було вказано! Таким чином, ви можете гнучко створювати анотації для згенерованих властивостей, використовуючи вбудований синтаксис C# і без обмежень на типи атрибутів, які підтримуються цією функцією. 

Примітка: згенерований код дещо відрізняється і включає додаткові оптимізації продуктивності, не показані тут.

Ви можете знайти всі документи про нові генератори коду тут, а якщо ви віддаєте перевагу відеоверсії, Джеймс Монтемагно також зняв кілька відео про них, наприклад, це.

Аналізатори MVVM Toolkit 

Цей випуск MVVM Toolkit також є першим, в якому представлені спеціальні аналізатори, що допомагають розробникам використовувати MVVM Toolkit найкращим чином. Тобто, MVVM Toolkit більше не буде просто видавати діагностику для функцій, які використовуються неправильно (тобто таким чином, що призведе до помилки), тепер він також буде показувати рекомендації щодо покращення коду та уникнення поширених помилок! 

Перший аналізатор розглядає поширену помилку при використанні атрибута [ObservableProperty]. Розглянемо такий приклад:

Розробники неодноразово стикалися з такою проблемою, коли випадково присвоювали значення полю (а не згенерованій властивості), а потім стикалися з тим, що інтерфейс не відображав зміни, без чіткого пояснення, чому це сталося. Новий аналізатор допоможе у цих випадках, і він позначатиме всі присвоєння полів, що підтримують видиму властивість, показуючи діагностику, яка запропонує посилатися на створену властивість замість неї. Більше жодних загадкових сповіщень про відсутність властивості!

Другий новий аналізатор має на меті допомогти зменшити розмір двійкових файлів у додатках, що використовують MVVM Toolkit. Як вже згадувалося в анонсі 8.0.0, MVVM Toolkit включає декілька атрибутів (таких як [ObservableObject]), які дозволяють генераторам вставляти весь код, необхідний для реалізації інтерфейсів INotifyPropertyChanged та INotifyPropertyChanging (опціонально з додатковими допоміжними засобами) у вже наявні класи. Це особливо корисно у випадках, коли клас вже успадковується від іншого типу, ніж ObservableObject: ви можете використовувати атрибут і мати доступ до тих самих допоміжних функцій, не переробляючи логіку самостійно.

Однак це стосується лише тих випадків, коли успадкування неможливе: якщо ж це не так, краще просто успадкувати від ObservableObject і скористатися перевагами зменшеного розміру двійкового файлу, оскільки компілятору не доведеться копіювати ті самі допоміжні функції знову і знову у кожному типі. Розглянемо цей приклад:

Тут MyViewModel не успадковує від жодного типу, тому їй краще успадкувати від ObservableObject, а не використовувати атрибут [ObservableObject], щоб отримати вигоду від покращення бінарного розміру. Новий аналізатор позначатиме всі сценарії, подібні до цього, пропонуючи використовувати успадкування. Це особливо допоможе новачкам, які можуть не розуміти нюансів двох різних підходів і не знати, як зробити вибір. У таких випадках аналізатор тепер буде поруч, щоб допомогти.

Оптимізація генератора вихідних кодів MVVM Toolkit 

Як вже згадувалося, цей новий випуск також містить значні оптимізації продуктивності MVVM Toolkit, щоб ще більше покращити UX для розробників, особливо при роботі над дуже великими проєктами.

Ось лише деякі з покращень у цьому напрямку:

1. Додано багатоцільове орієнтування для Roslyn 4.3 (#428, #462): генератори вихідних кодів MVVM Toolkit тепер використовуватимуть орієнтир на Roslyn 4.3, якщо він підтримується, щоб вони могли підключатися до деяких оптимізованих API, якщо хост це підтримує. Ця функція автоматично вмикається при зверненні до MVVM Toolkit.

 

2. Використання ForAttributeWithMetadataName (#436): було переключено генератори на новий високорівневий API Roslyn для зіставлення атрибутів, що значно покращує продуктивність генераторів, які спрацьовують за певними атрибутами. Наприклад, [ObservableProperty] тепер використовує цю можливість.

3. Перенесено діагностику в діагностичні аналізатори (#433, #434): було перенесено майже всю діагностику в діагностичні аналізатори, які виконуються поза процесом і незалежно від генераторів вихідних кодів. Це значно зменшує накладні витрати при наборі коду, оскільки вся логіка діагностики тепер виконується в окремому процесі й не може сповільнювати роботу IntelliSense.

4. Припинено використання символів у інкрементних провайдерах (#435): було оновлено всі інкрементні провайдери, щоб більше не поширювати символи. Це може зменшити використання пам’яті, оскільки розповсюдження символів може призвести до того, що Roslyn надмірно викорінюватиме об’єкти компіляції.

5. Більше оптимізацій продуктивності (#447, #460, #469, #487, #489): було переглянуто всі інкрементальні моделі та інкрементальні конвеєри, що значно покращило продуктивність та зменшило виділення пам’яті.

Розширення месенджерів IObservable 

 

Ще однією запитуваною функцією, особливо розробниками, які інтенсивно використовують API у стилі Reactive у своїх додатках, була можливість об’єднати функціональність API месенджерів у MVVM Toolkit. Тепер це підтримується завдяки новим розширенням IObservable для інтерфейсу IMessenger. Їх можна використовувати наступним чином:

 

… Ось і все! Це розширення створить об’єкт IObservable, який можна використовувати для підписки на повідомлення і динамічної реакції на них. Також підтримується вказівка різних токенів за допомогою окремих перевантажень. Ось ще один приклад, що демонструє наскрізне використання нового API:

Підтримка .NET 7 та C# 11 

Цей новий випуск .NET Community Toolkit також додає .NET 7 TFM до пакета HighPerformance і містить кілька змін, що дозволяють скористатися новими можливостями мови C# 11, зокрема, посиланнями на поля (ref fields).

Наступні типи більше не знаходяться у попередньому перегляді й були оновлені для використання нових правил безпеки ref-полів:

Приклад, де вони можуть бути використані, наведено нижче:

Тобто, тип NullableRef фактично дозволяє методу мати параметр out ref T, який не може бути виражений в C# іншим чином. Планується також розширити поверхню API цих типів у майбутньому, щоб ці типи могли стати простою у використанні альтернативою GC-ref арифметиці з використанням типу Unsafe, яка також може бути візуально більш схожою на традиційну арифметику з вказівниками.

 

Крім того, всі типи ref-структур, яких ще не було у попередньому перегляді, було оновлено для внутрішнього використання полів ref для покращення продуктивності. До них відносяться:

Інші зміни 

У цьому новому випуску набагато більше змін!

Ви можете переглянути повний список змін на сторінці релізу на GitHub.

Розпочинайте прямо зараз! 

Ви можете знайти весь вихідний код у репозиторії GitHub, деякі рукописні документи на MS learn та повні посилання на API на вебсайті браузера .NET API. Якщо ви хочете зробити свій внесок, не соромтеся повідомляти про проблеми або ділитися з нами своїм досвідом! Щоб стежити за обговоренням у Twitter, використовуйте хештег #CommunityToolkit. Всі ваші відгуки дуже допомагають формувати напрямок розвитку цих бібліотек, тому обов’язково діліться ними!

Більше ресурсів 

Якщо ви хочете дізнатися більше про MVVM Toolkit, ви також можете переглянути це відео з нещодавньої конференції .NET Conf 2022, де показано, як можна використовувати MVVM Toolkit, новий генератор коду та всі нові функції в 8.1:

Існує ціла екосистема доступних Toolkit’ів з безліччю корисних API для створення .NET-додатків! Дізнайтеся більше про них у документації MS learn!

 

Вдалого кодування!

Source



Posted on 13. December 2022

.NET 7 Покращення мережевих можливостей


.NET 7 Покращення мережевих можливостей

Оскільки нещодавно вийшов .NET 7, хотілося б познайомити вас з деякими цікавими змінами та доповненнями, зробленими в мережевому просторі. У цій статті йтиметься про зміни .NET 7 у просторі HTTP, нові API-інтерфейси QUIC, мережеву безпеку та WebSockets.

HTTP

Удосконалена обробка невдалих спроб з’єднання

У версіях до .NET 6, якщо в пулі з’єднань не було доступного з’єднання, новий HTTP-запит завжди створював нову спробу з’єднання і чекав на неї (якщо це дозволяли налаштування обробника, наприклад, MaxConnectionsPerServer для HTTP/1.1 або EnableMultipleHttp2Connections для HTTP/2). Недоліком цього сценарію є те, що якщо встановлення цього з’єднання займе деякий час, а тим часом стане доступним інше з’єднання, цей запит продовжить очікувати на з’єднання, яке він створив, що призведе до збільшення затримки. У .NET 6.0 було замінено це на обробку запитів на тому з’єднанні, яке стане доступним першим, незалежно від того, чи це щойно створене з’єднання, чи те, яке стало готовим до обробки запиту в цей час. Нове з’єднання все одно створюється (з урахуванням обмежень), і якщо воно не було використане ініціатором запиту, воно об’єднується в пул, щоб наступні запити могли його використати.

На жаль, реалізація .NET 6.0 виявилася проблематичною для деяких користувачів: невдала спроба з’єднання також призводить до невдачі запиту на початку черги запитів, що може призвести до несподіваних відмов запитів у певних сценаріях. Крім того, якщо в пулі є відкладене з’єднання, яке ніколи не стане доступним, наприклад, через несправність сервера або проблеми з мережею, нові вхідні запити, пов’язані з ним, також гальмуватимуться і можуть завершитися в тайм-ауті.

У .NET 7.0 було впроваджено наступні зміни для усунення цих проблем:

1. Невдала спроба з’єднання може призвести до невдачі лише того запиту, який її ініціював, але ніколи не може призвести до невдачі запиту, який не пов’язаний з нею. Якщо початковий запит було оброблено до того моменту, коли з’єднання було розірвано, то помилка з’єднання ігнорується (dotnet/runtime#62935).

 

2. Якщо запит ініціює нове з’єднання, але потім обробляється іншим з’єднанням з пулу, нова спроба з’єднання буде автоматично завершена через короткий проміжок часу, незалежно від ConnectTimeout. Завдяки цій зміні, зупинені з’єднання не будуть зупиняти непов’язані запити (dotnet/runtime#71785). Зауважте, що невдачі таких “відкинутих” спроб з’єднання відбуватимуться у фоновому режимі й ніколи не стануть відомі користувачеві, єдиний спосіб їх побачити – увімкнути телеметрію.

HttpHeaders зчитують безпеку потоку

Колекції HttpHeaders ніколи не були безпечними для потоків. Доступ до заголовка може призвести до лінивого розбору його значення, що може спричинити модифікацію базових структур даних.

До .NET 6 одночасне читання з колекції у більшості випадків було безпечним для потоків.

Починаючи з .NET 6, розбір заголовків став менше блокуватися, оскільки в ньому зникла внутрішня потреба. Через цю зміну з’явилося багато прикладів помилкового одночасного доступу користувачів до заголовків, наприклад, у gRPC (dotnet/runtime#55898),, NewRelic (newrelic/newrelic-dotnet-agent#803) або навіть у самому HttpClient (dotnet/runtime#65379). Порушення безпеки потоків у .NET 6 може призвести до дублювання/спотворення значень заголовків або генерування різних винятків під час зчитування/доступу до заголовків.

.NET 7 робить поведінку заголовків більш інтуїтивно зрозумілою. Колекція HttpHeaders тепер відповідає гарантіям потокової безпеки Словника:

Колекція може підтримувати декілька читачів одночасно, якщо її не модифіковано. У рідкісних випадках, коли перерахування конкурує з доступом на запис, колекція повинна бути заблокована протягом усього перерахування. Щоб дозволити доступ до колекції декільком потокам для читання і запису, потрібно реалізувати власну синхронізацію.

Цього було досягнуто наступними змінами:

“Читання з перевіркою” недійсного значення не призводить до видалення недійсного значення - dotnet/runtime#67833 

 

Одночасне читання є безпечним для потоків – dotnet/runtime#68115.

Виявлення помилок протоколів HTTP/2 і HTTP/3

Протоколи HTTP/2 і HTTP/3 визначають коди помилок на рівні протоколу у RFC 7540, розділ 7 і RFC 9114, розділ 8.1, наприклад, REFUSED_STREAM (0×7) в HTTP/2 або H3_EXCESSIVE_LOAD (0×0107) в HTTP/3. На відміну від кодів HTTP-статусу, це низькорівнева інформація про помилки, яка не є важливою для більшості користувачів HttpClient, але вона допомагає в розширених сценаріях HTTP/2 або HTTP/3, зокрема grpc-dotnet, де розпізнавання помилок протоколу є життєво важливим для реалізації повторних спроб клієнта.

Було створено нове виключення HttpProtocolException для зберігання коду помилки на рівні протоколу у його властивості ErrorCode.

При безпосередньому виклику HttpClient, HttpProtocolException може бути внутрішнім виключенням HttpRequestException:

При роботі з відповіддю потоку HttpContent він передається безпосередньо:

HTTP/3

Підтримка HTTP/3 у HttpClient вже була реалізована у попередній версії .NET, тому основні зусилля у цій сфері було зосереджено на базовому System.Net.Quic. Попри це, було внесено декілька виправлень та змін у .NET 7.

 

Найважливішою зміною є те, що HTTP/3 тепер увімкнено за замовчуванням (dotnet/runtime#73153). Це не означає, що відтепер всі HTTP-запити будуть віддавати перевагу HTTP/3, але в певних випадках вони можуть оновитися до нього. Щоб це сталося, запит повинен вибрати оновлення версії за допомогою HttpRequestMessage.VersionPolicy, встановленого в RequestVersionOrHigher. Потім, якщо сервер оголосить HTTP/3 повноваження в заголовку Alt-Svc, HttpClient буде використовувати його для подальших запитів, див. RFC 9114, розділ 3.1.1.

Ось декілька інших цікавих змін:

1. Телеметрія HTTP була розширена на HTTP/3 – dotnet/runtime#40896.

2. Покращено деталі винятків у випадку неможливості встановлення з’єднання QUIC – dotnet/runtime#70949.

 

3. Виправлено правильне використання заголовка Host для ідентифікації імені сервера (SNI) – dotnet/runtime#57169.

QUIC

QUIC – це новий протокол транспортного рівня. Нещодавно його було стандартизовано у RFC 9000. Він використовує UDP як базовий протокол і є безпечним за своєю суттю, оскільки вимагає використання TLS 1.3, див. RFC 9001. Ще одна цікава відмінність від відомих транспортних протоколів, таких як TCP і UDP, полягає в тому, що він має вбудоване потокове мультиплексування на транспортному рівні. Це дозволяє мати декілька паралельних, незалежних потоків даних, які не впливають один на одного.

Сам по собі QUIC не визначає ніякої семантики для даних, що обмінюються, оскільки це транспортний протокол. Він скоріше використовується в протоколах прикладного рівня, наприклад, в HTTP/3 або в SMB over QUIC. Він також може бути використаний для будь-якого користувацького протоколу.

 

Протокол має багато переваг над TCP з TLS. Наприклад, швидше встановлення з’єднання, оскільки він не вимагає стільки обходів, як TCP з TLS. Або уникнення проблеми блокування головної лінії, коли один втрачений пакет не блокує дані всіх інших потоків. З іншого боку, використання QUIC має свої недоліки. Оскільки це новий протокол, його впровадження все ще триває і є обмеженим. Крім того, трафік QUIC може навіть блокуватися деякими мережевими компонентами.

QUIC в .NET

Реалізацію QUIC в .NET 5 представлено в бібліотеці System.Net.Quic. Однак до цього часу бібліотека була суто внутрішньою і слугувала лише для власної реалізації HTTP/3. З виходом .NET 7 бібліотека стає загальнодоступною і доступні її API. Оскільки в цій версії API використовувалися лише HttpClient та Kestrel, було вирішено залишити їх у вигляді функції попереднього перегляду.

Це дає можливість доопрацювати API в наступному релізі, перш ніж він набуде остаточного вигляду.

 

З точки зору реалізації, System.Net.Quic залежить від MsQuic, нативної реалізації протоколу QUIC. В результаті, підтримка платформи System.Net.Quic і залежності успадковані від MsQuic і задокументовані в залежності від платформи HTTP/3. Коротко кажучи, бібліотека MsQuic постачається як частина .NET для Windows. Для Linux libmsquic необхідно встановити вручну за допомогою відповідного менеджера пакунків. Для інших платформ, як і раніше, можна зібрати MsQuic вручну, чи то для SChannel, чи то для OpenSSL, і використовувати її з System.Net.Quic.

Огляд API

System.Net.Quic містить три основні класи, які дозволяють використовувати протокол:

QuicListener – клас на стороні сервера для приймання вхідних з’єднань.

QuicConnection – QUIC з’єднання, що відповідає RFC 9000 Section 5.

QuicStream – потік QUIC, що відповідає RFC 9000 Section 2.

Але перед будь-яким використанням цих класів користувацький код повинен перевірити, чи підтримується QUIC, оскільки libmsquic може бути відсутнім, або TLS 1.3 може не підтримуватися. Для цього і QuicListener, і QuicConnection мають статичну властивість IsSupported:

 

Зауважте, що наразі обидві ці властивості синхронізовані й показуватимуть однакове значення, але це може змінитися у майбутньому. Тому рекомендується перевірити QuicListener.IsSupported для серверних сценаріїв і QuicConnection.IsSupported для клієнтських.

QuicListener

 

QuicListener являє собою клас на стороні сервера, який приймає вхідні з’єднання від клієнтів. Слухач створюється і запускається за допомогою статичного методу QuicListener.ListenAsync. Метод приймає екземпляр класу QuicListenerOptions з усіма налаштуваннями, необхідними для запуску слухача і приймання вхідних з’єднань. Після цього слухач готовий роздавати з’єднання через AcceptConnectionAsync. З’єднання, що повертаються цим методом, завжди повністю з’єднані, що означає, що рукостискання TLS завершено і з’єднання готове до використання. Нарешті, щоб припинити прослуховування і звільнити всі ресурси, необхідно викликати DisposeAsync.

 

Приклад використання QuicListener:

 

Більш детальну інформацію про те, як було розроблено цей клас, можна знайти у QuicListener API Proposal (dotnet/runtime#67560).

QuicConnection

QuicConnection – це клас, який використовується як для серверних, так і для клієнтських QUIC-з’єднань. З’єднання на стороні сервера створюються внутрішньо слухачем і роздаються через QuicListener.AcceptConnectionAsync. Клієнтські з’єднання повинні бути відкриті й підключені до сервера. Як і у випадку зі слухачем, існує статичний метод QuicConnection.ConnectAsync, який створює та встановлює з’єднання. Він приймає екземпляр класу QuicClientConnectionOptions, аналогічного класу QuicServerConnectionOptions. Після цього робота зі з’єднанням не відрізняється між клієнтом і сервером. Він може відкривати вихідні потоки й приймати вхідні. Він також надає властивості з інформацією про з’єднання, такі як LocalEndPoint, RemoteEndPoint або RemoteCertificate.

Після завершення роботи зі з’єднанням його потрібно закрити та скинути. Протокол QUIC вимагає використання коду програмного рівня для негайного закриття, див. RFC 9000, розділ 10.2. Для цього можна викликати CloseAsync з кодом програмного рівня або, якщо ні, DisposeAsync використає код, наданий у QuicConnectionOptions.DefaultCloseErrorCode. У будь-якому випадку, DisposeAsync має бути викликано наприкінці роботи зі з’єднанням, щоб повністю звільнити всі пов’язані з ним ресурси.

Приклад використання QuicConnection:

 

Більш детально про те, як був розроблений цей клас, можна прочитати в QuicConnection API Proposal (dotnet/runtime#68902).

QuicStream

 

QuicStream – це тип, який використовується для надсилання та отримання даних у протоколі QUIC. Він походить від звичайного потоку і може використовуватися як такий, але він також пропонує кілька особливостей, які є специфічними для протоколу QUIC. По-перше, потік QUIC може бути однонапрямний або двонапрямний, див. RFC 9000, розділ 2.1. Двонапрямний потік може надсилати та отримувати дані з обох сторін, тоді як однонапрямний потік може тільки писати зі сторони, що ініціює та читати зі сторони, що приймає. Кожен одноранговий комп’ютер може обмежити кількість одночасних потоків кожного типу, див. QuicConnectionOptions.MaxInboundBidirectionalStreams та QuicConnectionOptions.MaxInboundUnidirectionalStreams.

Ще однією особливістю потоку QUIC є можливість явно закрити сторону запису посеред роботи з потоком, див. перевантаження CompleteWrites або WriteAsync-system-boolean-system-threading-cancellationtoken)) з аргументом completeWrites. Закриття сторони запису дає змогу одноранговій системі знати, що дані більше не надходитимуть, проте вона може продовжувати надсилати (у випадку двонапрямного потоку). Це корисно в таких сценаріях, як обмін HTTP-запитами/відповідями, коли клієнт надсилає запит і закриває сторону запису, щоб повідомити серверу, що на цьому вміст запиту закінчився. Сервер все ще може відправити відповідь після цього, але знає, що більше ніяких даних від клієнта не надійде. У випадку помилкових ситуацій можна перервати потік як на стороні запису, так і на стороні читання, див. розділ Переривання. Поведінка окремих методів для кожного типу потоку підсумована у наступній таблиці (зауважте, що і клієнт, і сервер можуть відкривати й приймати потоки):

 

На додаток до цих методів, QuicStream пропонує дві спеціалізовані властивості для отримання сповіщень про закриття потоку для читання або запису: ReadsClosed та WritesClosed. Обидві властивості повертають завдання, яке завершується закриттям відповідної сторони потоку, незалежно від того, чи було воно успішне, чи перериване, в останньому випадку завдання буде містити відповідний виняток. Ці властивості корисні, коли користувацькому коду потрібно знати про закриття сторони потоку без виклику ReadAsync або WriteAsync.

 

Нарешті, коли робота з потоком завершена, його потрібно вилучити за допомогою DisposeAsync. Програма переконається, що сторона читання та/або запису – залежно від типу потоку – закрита. Якщо потік не було прочитано належним чином до кінця, програма видасть еквівалент Abort(QuicAbortDirection.Read). Однак, якщо потік не було закрито на стороні запису, він буде поступово закритий, як це було б у випадку з CompleteWrites. Причина такої різниці полягає в тому, щоб переконатися, що сценарії, які працюють зі звичайним потоком, поводяться очікувано і ведуть до успішного завершення. Розглянемо наступний приклад:

Приклад використання QuicStream у клієнтському сценарії:

І приклад використання QuicStream у серверному сценарії:

Більш детально про те, як був розроблений цей клас, можна прочитати в QuicStream API Proposal (dotnet/runtime#69675).

Безпека

Узгодження API

Автентифікація Windows – це загальний термін для позначення різних технологій, що використовуються на підприємствах для автентифікації користувачів і програм за допомогою центрального органу, зазвичай контролера домену. Вона уможливлює такі сценарії, як єдиний вхід до служб електронної пошти або програм інтрамережі. Основними технологіями, що використовуються для автентифікації, є Kerberos, NTLM і протокол Negotiate, де для конкретного сценарію автентифікації вибирається найбільш відповідна технологія.

До .NET 7 автентифікація Windows була доступна у високорівневих API, таких як HttpClient (схеми автентифікації Negotiate і NTLM), SmtpClient (схеми автентифікації GSSAPI й  NTLM), NegotiateStream, ASP.NET Core і у клієнтських бібліотеках SQL Server. Хоча вона охоплює більшість сценаріїв для кінцевих користувачів, проте обмежує можливості авторів бібліотек. Інші бібліотеки, такі як клієнт Npgsql PostgreSQL, MailKit, клієнт Apache Kudu та інші, повинні були вдаватися до різних хитрощів, щоб реалізувати ті ж схеми автентифікації для низькорівневих протоколів, які не були побудовані на HTTP або інших доступних високорівневих будівельних блоках.

.NET 7 представляє новий API, що надає низькорівневі будівельні блоки для виконання обміну автентифікацією для вищезгаданих протоколів, див. dotnet/runtime#69920. Як і всі інші API в .NET, він побудований з урахуванням кросплатформної сумісності. На Linux, macOS, iOS та інших подібних платформах він використовує системну бібліотеку GSSAPI. На Windows – бібліотеку SSPI. Для платформ, де системна реалізація недоступна, таких як Android і tvOS, існує обмежена реалізація лише для клієнтів.

Як користуватися API

Щоб зрозуміти, як працює API автентифікації, почнімо з прикладу того, як виглядає сеанс автентифікації в такому високорівневому протоколі, як SMTP. Приклад взято з документації до протоколу Microsoft, яка пояснює його більш детально.

Аутентифікація починається з того, що клієнт генерує маркер виклику. Потім сервер генерує відповідь. Клієнт обробляє відповідь, і на сервер надсилається новий запит. Цей обмін запитами/відповідями може відбуватися кілька разів. Він завершується, коли одна зі сторін відхиляє автентифікацію або коли обидві сторони приймають автентифікацію. Формат маркерів визначається протоколами автентифікації Windows, а інкапсуляція є частиною специфікації протоколу високого рівня. У цьому прикладі протокол SMTP готує код 334, щоб повідомити клієнту, що сервер надав відповідь на автентифікацію, а код 235 вказує на успішну автентифікацію.

Основна частина нового API зосереджена навколо нового класу NegotiateAuthentication. Він використовується для визначення контексту для автентифікації на стороні клієнта або на стороні сервера. Існують різні варіанти визначення вимог для створення сеансу автентифікації, наприклад, вимога шифрування або визначення конкретного протоколу (Negotiate, Kerberos або NTLM), який має бути використаний. Після визначення параметрів автентифікація продовжується шляхом обміну автентифікаційними запитами/відповідями між клієнтом і сервером. Для цього використовується метод GetOutgoingBlob. Він може працювати як з байтовими діапазонами, так і з рядками, закодованими в base64.

Наступний код виконає частину автентифікації для поточного користувача на тій самій машині як для клієнта, так і для сервера:

Після встановлення сеансу автентифікації екземпляр NegotiateAuthentication можна використовувати для підписання/шифрування вихідних повідомлень і перевірки/дешифрування вхідних повідомлень. Це робиться за допомогою методів Wrap і Unwrap.

Варіанти перевірки сертифіката

Коли клієнт отримує сертифікат сервера, або навпаки, якщо запитується сертифікат клієнта, сертифікат перевіряється за допомогою X509Chain. Перевірка відбувається завжди, навіть якщо передбачено RemoteCertificateValidationCallback, і під час перевірки можуть бути завантажені додаткові сертифікати. Було піднято декілька питань, оскільки не було способу контролювати таку поведінку. Серед них були прохання повністю запобігти завантаженню сертифікатів, поставити тайм-аут на нього або надати власне сховище для отримання сертифікатів. Щоб вирішити цю групу проблем, було вирішено ввести нову властивість CertificateChainPolicy в SslClientAuthenticationOptions і SslServerAuthenticationOptions. Мета цієї властивості – перевизначити поведінку SslStream за замовчуванням при побудові ланцюжка під час операції AuthenticateAsClientAsync / AuthenticateAsServerAsync. За звичайних обставин X509ChainPolicy будується автоматично у фоновому режимі. Але якщо вказати цю нову властивість, вона матиме пріоритет і буде використовуватися замість неї, надаючи користувачеві повний контроль над процесом перевірки сертифіката.

Використання ланцюгової політики може виглядати так:

Більше інформації можна знайти в пропозиції API (dotnet/runtime#71191).

Продуктивність

Більшість покращень продуктивності мережі в .NET 7 описано в статті Стівена “Покращення продуктивності в .NET 7 – Мережа”, але деякі з них варто згадати ще раз.

Резюме TLS

Встановлення нового TLS-з’єднання є досить затратною операцією, оскільки вона вимагає декількох кроків і декількох циклів в обидва боки. У сценаріях, де з’єднання з одним і тим же сервером створюється дуже часто, час, витрачений на рукостискання, буде збільшуватися. TLS пропонує функцію для зменшення цього часу, яка називається відновленням сеансу, див. RFC 5246, розділ 7.3 і RFC 8446, розділ 2.2. Коротко кажучи, під час рукостискання клієнт може відправити ідентифікатор раніше встановленої TLS-сесії, і якщо сервер погоджується, контекст безпеки відновлюється на основі кешованих даних з попереднього з’єднання. Незважаючи на те, що механізми відрізняються для різних версій TLS, кінцева мета однакова – заощадити час в обидва боки і процесорний час при відновленні з’єднання з раніше підключеним сервером. Ця функція автоматично надається SChannel в Windows, але в OpenSSL в Linux для її включення знадобилося внести кілька змін:

1. На стороні сервера (без статусу) – dotnet/runtime#57079 та dotnet/runtime#63030.

2. Клієнтська частина – dotnet/runtime#64369.

3. Керування розміром кешу – dotnet/runtime#69065.

Якщо кешування контексту TLS не є бажаним, його можна вимкнути у всьому процесі за допомогою змінної оточення “DOTNET_SYSTEM_NET_SECURITY_DISABLETLSRESUME” або через AppContext.SetSwitch “System.Net.Security.TlsCacheSize”.

“Зшивання” OCSP

 

“Зшивання” онлайн-сертифікатів (Online Certificate Status Protocol, OCSP) – це механізм надання сервером підписаного і позначеного часом доказу (OCSP-відповідь) того, що надісланий сертифікат не було відкликано, див. RFC 6961. В результаті клієнту не потрібно звертатися до самого OCSP-сервера, що зменшує кількість запитів, необхідних для встановлення з’єднання, а також навантаження на OCSP-сервер. А оскільки відповідь OCSP повинна бути підписана центром сертифікації (ЦС), вона не може бути підроблена сервером, що надає сертифікат. Ця функція TLS не використовувалась до цього випуску, більш детальну інформацію дивіться на dotnet/runtime#33377.

Узгодженість між платформами

Відомо, що деякі функції, які надає .NET, доступні лише на певних платформах. Але з кожним випуском команди намагаються ще більше скоротити цей розрив. У .NET 7 було внесено кілька змін у сфері мережевої безпеки, щоб усунути цю нерівність:

1. Підтримка автентифікації після рукостискання в Linux для TLS 1.3 – dotnet/runtime#64268

2. Віддалений сертифікат тепер налаштовується на Windows у SslClientAuthenticationOptions.LocalCertificateSelectionCallbackdotnet/runtime#65134

3. Підтримка надсилання імен довірених центрів сертифікації в TLS-рукостисканні на OSX та Linux – dotnet/runtime#65195.

WebSockets

Деталі відповіді на рукостискання WebSocket

 

До .NET 7 частина відповіді сервера на відкриття рукостискання WebSocket (HTTP-відповідь на запит оновлення) була прихована всередині реалізації ClientWebSocket, і всі помилки рукостискання з’являлися як WebSocketException без особливої деталізації, окрім повідомлення про виняток. Однак інформація про заголовки HTTP-відповіді та код статусу може бути важливою як у випадку збою, так і у випадку успіху.

У разі збою код стану HTTP може допомогти відрізнити помилки, які можна виправити, від помилок, які не можна виправити (наприклад, сервер взагалі не підтримує WebSockets, або це була просто транзиторна мережева помилка). Заголовки також можуть містити додаткову інформацію про те, як виправити ситуацію. Заголовки корисні навіть у випадку успішного рукостискання WebSocket, наприклад, вони можуть містити токен, прив’язаний до сесії, інформацію про версію підпротоколу або про те, що сервер може незабаром вийти з ладу.

У .NET 7 додано параметр CollectHttpResponseDetails до ClientWebSocketOptions, який дозволяє збирати дані відповіді на оновлення в екземплярі ClientWebSocket під час виклику ConnectAsync. Пізніше ви зможете отримати доступ до цих даних за допомогою властивостей HttpStatusCode і HttpResponseHeaders екземпляра ClientWebSocket, навіть якщо ConnectAsync згенерує виключення. Зверніть увагу, що у винятковому випадку інформація може бути недоступною, тобто якщо сервер ніколи не відповідав на запит.

Також зверніть увагу, що у випадку успішного з’єднання та після споживання даних HttpResponseHeaders ви можете зменшити обсяг пам’яті ClientWebSocket, встановивши властивість ClientWebSocket.HttpResponseHeaders в нуль.

Надання зовнішнього HTTP-клієнта

За замовчуванням ClientWebSocket використовує кешований статичний екземпляр HttpMessageInvoker для виконання HTTP-запиту на оновлення. Однак існують певні параметри ClientWebSocketOptions, які запобігають кешуванню виклику, такі як Proxy, ClientCertificates або Cookies. Екземпляр HttpMessageInvoker з такими параметрами небезпечно використовувати повторно, і його потрібно створювати кожного разу, коли викликається ConnectAsync. Це призводить до багатьох непотрібних розподілів і робить неможливим повторне використання пулу з’єднань HttpMessageInvoker.

.NET 7 дозволяє передавати наявний екземпляр HttpMessageInvoker (наприклад, HttpClient) до виклику ConnectAsync, використовуючи перевантаження ConnectAsync(Uri, HttpMessageInvoker, CancellationToken). У цьому випадку HTTP-запит на оновлення буде виконано з використанням наданого екземпляра.

Зверніть увагу, що у випадку передачі користувацького виклику HTTP, не слід встановлювати жодну з наступних опцій ClientWebSocketOptions, замість цього їх слід встановити на виклик HTTP:

ClientCertificates

Cookies

Credentials

Proxy

RemoteCertificateValidationCallback

 

UseDefaultCredentials

 

 

Ось як ви можете налаштувати всі ці параметри для екземпляра HttpMessageInvoker:

WebSockets через HTTP/2

NET 7 також додає можливість використовувати протокол WebSocket через HTTP/2, як описано у RFC 8441. При цьому WebSocket-з’єднання встановлюється через один потік на HTTP/2-з’єднанні. Це дозволяє використовувати одне TCP-з’єднання для декількох WebSocket-з’єднань і HTTP-запитів одночасно, що призводить до більш ефективного використання мережі.

Щоб увімкнути WebSockets через HTTP/2, ви можете встановити параметр ClientWebSocketOptions.HttpVersion у значення HttpVersion.Version20. Ви також можете увімкнути оновлення/відновлення вже використаної версії HTTP, встановивши властивість ClientWebSocketOptions.HttpVersionPolicy. Ці параметри поводитимуться так само, як і HttpRequestMessage.Version та HttpRequestMessage.VersionPolicy.

Наприклад, наступний код буде шукати HTTP/2 WebSockets, і якщо з’єднання з WebSocket не вдасться встановити, він повернеться до HTTP/1.1:

Комбінація HttpVersion.Version11 і HttpVersionPolicy.RequestVersionOrHigher призведе до тієї ж поведінки, що і вище, тоді як HttpVersionPolicy.RequestVersionExact заборонить оновлення/відновлення вже використаної версії HTTP.

За замовчуванням встановлено HttpVersion = HttpVersion.Version11 та HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrLower, що означає використання лише HTTP/1.1.

Можливість мультиплексування WebSocket-з’єднань і HTTP-запитів через одне HTTP/2-з’єднання є важливою частиною цієї функції. Щоб вона працювала належним чином, вам потрібно передавати й повторно використовувати той самий екземпляр HttpMessageInvoker (наприклад, HttpClient) з вашого коду при виклику ConnectAsync, тобто використовувати перевантаження ConnectAsync(Uri, HttpMessageInvoker, CancellationToken). Це дозволить повторно використовувати пул з’єднань в екземплярі HttpMessageInvoker для мультиплексування.

Source




Posted on 13. November 2022

Нові можливості WPF у .NET 7


Нові можливості WPF у .NET 7

Спільнота WPF наповнена багатьма ентузіастами з дійсно дивовижним досвідом, і ця публікація має на меті висвітлити те, що було зроблено в репозиторії dotnet/wpf за останні кілька місяців. Щира подяка учасникам, які постійно працюють над покращенням WPF. Ось короткий огляд того, що було зроблено за останні кілька місяців у репозиторії dotnet/wpf.

Продуктивність

WPF в .NET 7 містить низку покращень, які не обмежуються лише непотрібними упакуваннями (boxing) та розпакуваннями (unboxing), використанням Span для маніпуляцій з рядками, кращим розподілом/перерозподілом об’єктів, покращенням пам’яті, рендерингом шрифтів і т.д., а й очищенням коду та звільненням місця для майбутньої роботи.

Упакування (boxing) / розпакування (unboxing)

 

Процеси boxing та unboxing вимагають значних обчислювальних затрат. Коли тип значення є упакованим, необхідно виділити та створити новий об’єкт. Незначною мірою, перетворення, необхідне для розпакування, також вимагає значних обчислювальних витрат.

Уникнення boxing при встановленні властивостей DependencyObject 

Припинення boxing WeakReferenceListEnumerator у використанні PresentationSource

Повторне використання об’єктів типу bool в UncommonField.SetValue

Зупинення boxing у Visual.SetDpiScaleVisualFlags

Уникайте boxing enumerator у XamlSchemaContext.UpdateNamespaceByUriList

Уникнення boxing enumerator списків/масивів у CreateTextLSRuns

 

Уникнення boxing enumerator списків у XamlObjectWriter.Logic_ConvertPositionalParamsToArgs

Розподіл

 

Чим більше об’єктів розміщено на купі, тим більше накладних витрат на відновлення цих об’єктів після завершення їхнього життєвого циклу. Зменшення кількості таких розподілів у пам’яті зменшує накладні витрати на GC.

Уникнення розподілів, пов’язаних з Hashtable, в AccessorTable

Уникнення розподілів, пов’язаних з Hashtable в DataBindEngine

Видалення розподілу закриття/делегування у ItemContainerGenerator

Уникнення виділення делегату для виклику ListCollectionView.PrepareComparer

Уникнення зайвого виділення byte[] у Baml2006Reader.Process_Header

Уникнення виділення Stack лише для того, щоб поглянути на нього

Припинення виділення непотрібного StringBuilders у ParsePropertyComments

Уникнення непотрібного перерозподілу StringBuilder у LookupAndSetLocalizabilityAttribute

Уникнення виняткового виділення рядків у StaticExtension.ProvideValue

Видалення непотрібного виділення рядків та рядків[] з MS.Internal.ContentType

Видалення деяких непотрібних StringBuilders

Видалення виділення підрядків з Baml2006Reader.Logic_GetFullXmlns

Не призначайте резервне ім’я в XamlNamespace.GetXamlType, якщо воно не потрібне

 

Уникнення зайвих розподілів перелічувачів у XamlDirective.GetHashCode

Різне

Уникнення надмірних викликів гетера індексу PropertyValues.

Зміцнення випадків відповідно до умов перегонів 

Усунення копіювання пам’яті під час читання даних шрифтів 

Невелике покращення продуктивності PathParser

Використання зрізу проміжку замість підрядка в AbbreviatedGeometryParser.ReadNumber

Уникнення непотрібного дублювання полів у NullableBooleanBox’ах

Змінення більшості не генетичних видів на генетичні

Деякі покращення в FrugalList

Уникнення зайвого Collection в обгортці CombineSources

Уникнення зайвого List<> (Список<>) в GetTextRunSpans

Доступність

 

З метою забезпечення доступності елементів керування WPF, нижче наведено вдосконалення продуктів, які були реалізовані у WPF.

1. WPF DataGrid/GridView ширину стовпчика можна змінити за допомогою комбінації клавіш ALT+стрілка вліво або вправо — Ширина стовпчика Datagrid може бути змінена за допомогою комбінації клавіш Alt + стрілка вліво / стрілка вправо.

2. Сортувати стовпець таблиці даних за допомогою клавіші F3 - Стовпці таблиці даних тепер можна сортувати (якщо для стовпця увімкнено сортування) за допомогою комбінації клавіш F3.

 

3. Голос диктора для пунктів меню, які можна перевірити — екранні диктори можуть коректно повідомляти про наявність пунктів меню, які можна перевірити.

Виправлення помилок

 

Хоча WPF залишається повністю підтримуваним і обслуговуваним на .NET Framework, більшість виправлень і всі нові функції будуть перенесені тільки в .NET Core, де є можливість вносити більші зміни. Спільнота допомогла усунути деякі застарілі помилки в цьому випуску.

FocusVisualStyle не можна перезаписати глобально 

CommandParameter робить недійсним CanExecute за допомогою miloush 

Проблеми з підказками

.NET 6 Зміна поведінки підказок у порівнянні з .NET 5 (помилка?)

Помилка підказки комбінованого елемента

ContextMenu перестає працювати, якщо його власника видалено з візуального дерева

 

Виправлено помилку округлення під час серіалізації glyphrun

Наведений вище список НЕ є вичерпним, і багато інших помилок було усунуто завдяки учасникам спільноти, які доклали зусиль для їх виправлення.

Модернізація інфраструктури

 

Однією з основних сфер для покращення, озвучених громадою, є рівень, за яким приймаються внески від громади. За допомогою наведених нижче модернізацій інфраструктури планується вплинути на рівень, за яким ми приймаємо внески від громади

 

 

Назва

Опис

Міграція тестового репозиторію

Кодова база WPF має понад 30 тисяч інтеграційних тестів. Ці тести забезпечують працездатність збірки з різними ОС та матрицею комбінацій .NET framework. В рамках відкритого доступу до тестової інфраструктури, планується перенести всі тести з внутрішньої на Github. Це також дозволить спільноті додавати власні тести до репозиторію тестів.

Більшість базових регресійних тестів з відкритим кодом, що дозволяє учасникам спільноти запускати ці тести локально і налагоджувати їх, якщо виникнуть проблеми з будь-яким з поданих PR-повідомлень.

Запуск базових тестів на кожен вхідний PR

Базові регресійні тести (також відомі як Daily Regression Tests або DRT(s)), які перевіряють базову поведінку елементів керування, необхідно запускати на кожному надісланому PR, щоб переконатися, що зміни не спричиняють регресії. Кінцева мета цієї процедури полягає в тому, щоб переконатися, що є система, яка дозволяє проводити тести на вхідних PR. Це дозволить скоротити час обробки PR, тим самим збільшивши швидкість, з якою нові зміни/виправлення можуть бути додані до репозиторію.

Зараз такі тести виконуються як частина збірки для кожного вхідного PR. У найближчі місяці планується вдосконалити ці конвеєри з точки зору звітування про стан виконання тестів, щоб уникнути ручного пошуку збоїв у журналах.


Поточна діяльність

1. Процес міграції сховища тестів все ще має велику підмножину тестів, які ще не перенесено.

2. Уможливлення запуску більшого набору тестових кейсів на поданих спільнотою PR, що покращило б час виконання зворотного зв’язку на PR.

3. Усунення нагромадження запитів на виправлення та проблеми.

Source



Posted on 13. November 2022

Анонс загальної доступності .NET MAUI для .NET 7

Анонс загальної доступності .NET MAUI для .NET 7

Близько шести місяців тому було представлено інтерфейс .NET Multi-platform App UI (MAUI), і сьогодні приємно повідомити про загальну доступність .NET MAUI в наступному великому релізі, .NET 7. Основна робота над .NET MAUI за цей короткий проміжок часу була спрямована на розв’язання найпопулярніших проблем, покращення продуктивності CollectionView, та впровадження функцій для настільних комп’ютерів, оскільки тепер доступна не лише мобільна, але й настільна версія. Цей випуск супроводжує випуск Visual Studio 17.4, а перші функції .NET MAUI перейшли з попередньої версії в стабільну версію для Mac.

 

.NET MAUI для .NET 7 підтримуватиметься до травня 2024 року. Це означає, що підтримка .NET MAUI для .NET 6 буде продовжена на 6 місяців до травня 2023 року. Підтримка .NET MAUI передбачає підтримку фреймворку .NET MAUI, а також .NET SDK для Android, CarPlay, iOS, macOS, Mac Catalyst і tvOS.

Теми .NET MAUI 7

У цьому випуску розглянуто найпопулярніші проблеми, що виникали у відгуках, і представлено нові функції для розробників десктопних програм. Основною темою ваших відгуків було сильне бажання покращити якість самого інструментарію. Для цього у даному випуску зроблено багато виправлень в основних елементах керування інтерфейсом користувача і макетах.

Пропонуємо вам ознайомитися з деякими з них:

Елемент керування мапою

У цьому випуску представлено елемент керування мапою .NET MAUI Map, оновлений з Xamarin.Forms. Як і інші елементи інтерфейсу, це крос-платформна абстракція нативного елемента керування мапою, що надається кожною платформою. Елемент керування мапою підтримує позначки, спеціальні позначки, малювання багатокутників, ліній та кіл, геокодування та геолокацію, а також запуск нативного картографічного додатка на пристрої, який ви використовуєте.

Продуктивність мобільного рендерингу

.NET MAUI для .NET 7 працює навіть швидше, ніж .NET 6, після 6 місяців роботи. Було оптимізовано шлях рендерингу для базових представлень, а також вирішено кілька проблем, які впливали на плавність прокрутки в елементі керування списком CollectionView . Джонатан Пепперс поділиться детальним оглядом цих покращень у наступній публікації в блозі.

Вдосконалення робочого столу

 

Завдяки тісній співпраці з компаніями, що створюють десктопні додатки з використанням .NET MAUI, вдалося включити деякі покращення, що базуються на їхніх сценаріях використання, зокрема:

 

  • Розмір і положення вікна
  • Контекстні меню
  • Підказки
  • Жест наведення вказівника
  • Клацання правою кнопкою миші

 

А також багато іншого!

Це лише основні моменти.

Ви дізнаєтесь більше в примітках до випуску, документації та зразках.

Примітки до випуску:

.NET MAUI 7.0.49

Android 33.0.4

iOS 16.0.1478

Документація

Зразки

Примітки щодо сумісності

.NET MAUI 7 сумісний з:

  • Android API 33
  • Tizen 7.0
  • Xcode 14.0.1 (iOS 16)
  • WinUI 1.1.5
Xcode 14.1 було випущено під час останнього циклу контролю якості, тому підтримка .NET буде додана у наступному випуску сервісу. Для швидкого використання Xcode 14.1 ви можете отримати доступ до збірок з публічного конвеєра збірок.

Як розпочати роботу

Щоб отримати доступ до .NET MAUI та .NET 7, встановіть Visual Studio 17.4. Створюючи новий .NET MAUI або клієнтський додаток .NET (Android, iOS, macOS, tvOS), виберіть .NET 7 у переліку фреймворків.

Щоб полегшити цей процес перегляньте  відео.

Оновлення з .NET 6

Щоб оновити свої проєкти з .NET 6 до .NET 7, відкрийте файл csproj і змініть цільові фреймворки (TFM) з 6 на 7.

Раніше:

Після:


Відгуки та пропозиції

На основі ваших побажань формуються інвестиції в .NET MAUI. Ось як ви можете вплинути на це.

Публікуйте нові випуски SDK на GitHub у репозиторії dotnet/maui

Додайте реакцію на вже наявні проблеми, які також торкнулися вас.

Використовуйте опцію  Visual Studio Feedback option, щоб надсилати проблеми, пов’язані з редагуванням, інтелектуальними можливостями, налагодженням, перезавантаженням, перезапуском, віддаленим Mac і т.д.

Source



 



Posted on 13. November 2022

.NET 7 доступна вже сьогодні

.NET 7 доступна вже сьогодні


Завантажте .NET 7 вже сьогодні!

.NET 7 підвищує продуктивність ваших додатків та надає нові можливості для C# 11/F# 7, .NET MAUI, ASP.NET Core/Blazor, Web API, WinForms, WPF та інших. З .NET 7 ви також можете легко контейнеризувати свої проєкти .NET 7, налаштовувати робочі процеси CI/CD в діях GitHub і досягати хмарної спостережливості.

.NET залишається однією з найшвидших, найулюбленіших і найнадійніших платформ з великою екосистемою пакетів .NET, яка включає понад 330 000 пакетів.

Завантаження та оновлення

Ви можете завантажити безплатну версію .NET 7 вже сьогодні для Windows, macOS та Linux.

Інсталятори та двійкові файли

Зображення контейнерів

Пакунки для Linux

Примітки до випуску

Кардинальні зміни

Відомі проблеми

Трекер проблем на GitHub

.NET 7 забезпечує просте оновлення, якщо ви використовуєте версію .NET Core, і має кілька вагомих причин для міграції, якщо ви використовуєте версію .NET Framework.

 

Visual Studio 2022 17.4 також доступна сьогодні. Розробка .NET 7 у Visual Studio 2022 надає розробникам найкращі у своєму класі інструменти для підвищення продуктивності. Щоб дізнатися, що нового у Visual Studio 2022, перегляньте блоги про Visual Studio 2022.

Що нового в .NET 7

NET 7 випускається разом з кількома іншими продуктами, бібліотеками та платформами, які до неї входять:

ASP.NET Core 7

Entity Framework Core 7

.NET MAUI

Форми Windows

WPF

 

Оrleans 7

У цьому блозі висвітлено основні теми, на яких зосередилися команди .NET:

1. Об’єднані

One BCL

Нові TFM

Вбудована підтримка ARM64

Покращена підтримка .NET на Linux

2. Сучасні

Постійне підвищення продуктивності

Підвищення продуктивності розробників, як-от контейнерні робочі процеси

Створення кросплатформних мобільних та десктопних додатків з однієї кодової бази

3. .NET для хмарних додатків

Легко створювати та розгортати розподілені хмарні програми

4. Прості

Спрощуйте та пишіть менше коду з C# 11

Покращення HTTP/3 та мінімальних API для хмарних додатків

5. Продуктивні

Численні покращення

 

Нижче подано ці теми детальніше, а також пояснено, чому ця робота є важливою.

Сценарії

NET 7 настільки універсальна, що ви можете створити будь-який додаток на будь-якій платформі.

Розгляньмо деякі сценарії, яких ви можете досягти за допомогою .NET, починаючи відтепер:

Викликайте наявну .NET бібліотеку з коду React, що працює у браузері, включивши оптимізоване середовище виконання .NET, оптимізоване для роботи на WebAssembly.

Отримайте доступ до вмісту JSON-документа, що зберігається у вашій базі даних SQL Server, використовуючи строго типізований C#.

Швидко створюйте та розгортайте захищену кінцеву точку REST з автоматичним документуванням за допомогою OpenAPI, написавши лише кілька рядків коду.

Створіть оптимізовану нативну програму, використовуючи компіляцію Ahead of Time (AOT) з вихідного коду C#, і опублікуйте її безпосередньо в образі контейнера.

Запустіть програму .NET Core, яка використовує вбудовані API для стиснення та архівування вмісту у поєднуваний з Linux файл tar.gz.

Реалізуйте своє бачення мобільного додатка для Android, iOS та Windows, використовуючи єдину кодову базу та дизайн, який створює нативний код та компоненти для кожної цільової платформи.

Скористайтеся перевагами продуктивності .NET 7, автоматично мігруючи застарілі програми за допомогою помічника з оновлення та модернізуйте вебслужби Windows Communication Foundation (WCF) за допомогою CoreWCF.

Спростіть розробникам запуск нових додатків за допомогою шаблонів, які відображають вашу архітектуру та дизайн.

 

Для роботи з комбінаціями клавіш та клавішами-модифікаторами у Unix/Linux краще використовувати Console.ReadKey.

1. Об’єднані

 

Одна бібліотека базового класу (BCL)

Випуск .NET 7 – це третій великий реліз на шляху до уніфікації .NET (починаючи з .NET 5 у 2016 році).

 

З .NET 7 ви навчитесь один раз і використовуватиме свої навички багаторазово за допомогою одного SDK, одного середовища виконання, одного набору базових бібліотек для створення різних типів додатків (хмарних, веб, настільних, мобільних, ігрових, для Інтернету речей та штучного інтелекту).

Орієнтація на .NET 7

Коли ви вибираєте фреймворк у додатку або бібліотеці, ви вказуєте набір API, який хочете зробити доступним. Орієнтуватися на .NET 7 так само просто, як змінити цільовий фреймворк у вашому проєкті.

Програми, націлені на цільовий фреймворк net7.0 (TFM), працюватимуть на всіх підтримуваних операційних системах і архітектурах процесорів. Вони надають вам доступ до всіх API у .NET 7, а також до багатьох специфічних для операційної системи, таких як:

net7.0-android

net7.0-ios

net7.0-маккаталізатор

net7.0-macos

net7.0-tvos

net7.0-windows

 

API, доступні через net7.0 TFM, призначені для роботи скрізь. Якщо ви сумніваєтеся, чи підтримується той, чи інший API у .NET 7, ви завжди можете звернутися до https://apisof.net/. Ось приклад нещодавно доданого інтерфейсу IJsonTypeInfoResolver, який, як ви бачите, тепер вбудовано в .NET 7:

ARM64

У міру того, як індустрія рухається в напрямку ARM, розвивається і .NET. Однією з найбільших переваг процесорів ARM є енергоефективність. Це забезпечує найвищу продуктивність при найнижчому енергоспоживанні. Іншими словами, ви можете робити більше з меншими витратами. У .NET 5  описано ініціативи щодо підвищення продуктивності, які було зроблено для ARM64.

Покращення продуктивності

Однією з проблем, з якою зіткнулася команда під час дослідження x64 та ARM64, було виявлення того, що розмір кешу L3 неправильно зчитується з машин ARM64. Було змінено евристику, щоб повертати приблизний розмір, якщо розмір кешу L3 не можна було отримати з ОС або BIOS машини. Тепер можна краще визначити кількість ядер для кешу L3.

Основна кількість

Розмір кешу L3

1~4

4MB

5~16

8MB

17~64

16MB

65+

32 МБ

 

 

Далі прийшло розуміння LSE atomics. Якщо ви не знайомі, це надає атомарні API для отримання ексклюзивного доступу до критично важливих областей. В машинах з архітектурою CISC x86-x64 операції read-modify-write (RMW) над пам’яттю можна виконати однією командою, додавши префікс lock.

Однак на машинах з RISC-архітектурою операції RMW заборонені, і всі операції виконуються через регістри. Тому для паралельних сценаріїв вони мають пару інструкцій. “Load Acquire” (ldaxr) отримує ексклюзивний доступ до області пам’яті так, що жодне інше ядро не може отримати до неї доступ, а “Store Release” (stlxr) звільняє доступ для інших ядер. Між цими парами виконуються критичні операції. Якщо операція stlxr завершилася невдало, тому що якийсь інший процесор працював з пам’яттю після того, як ви завантажили вміст за допомогою ldaxr, є код для повторної спроби (cbnz повертається назад, щоб повторити операцію).

 

ARM представила інструкції атомізації LSE у версії 8.1. За допомогою цих інструкцій такі операції можна виконувати з меншою кількістю коду і швидше, ніж у традиційній версії. Коли цю функцію увімкнули для Linux, а згодом поширили її на Windows, то побачили виграш у продуктивності близько 45%.


Покращення бібліотеки

Для оптимізації бібліотек, що використовують intrinsics, додано нові кросплатформні помічники. До них відносяться “хелпери” для Vector64, Vector128 та Vector256. Кросплатформні помічники дозволяють уніфікувати алгоритми векторизації шляхом заміни апаратно-специфічної intrinsics (бібліотека, що використовується в X Window System) на апаратно-діагностичну intrinsics. Це принесе користь користувачам на будь-якій платформі, але очікується, що ARM64 отримає найбільшу вигоду, оскільки розробники без досвіду роботи з ARM64 все одно зможуть використовувати “хелпери”, щоб скористатися перевагами апаратної специфіки Arm64.

Переписування API, таких як EncodeToUtf8 і DecodeFromUtf8, з реалізації SSE3 на векторну може дати до 60% покращень.

Аналогічне перетворення інших API, таких як NarrowUtf16ToAscii() та GetIndexOfFirstNonAsciiChar(), може показати виграш у продуктивності до 35%.

Вплив на продуктивність

 

Завдяки роботі команди в .NET 7, багато показників MicroBenchmarks покращилися на 10-60%. На початку роботи з .NET 7 кількість запитів в секунду (RPS) була нижчою для ARM64, але поступово подолала паритет з x64.

 

Аналогічно для латентності (вимірюваної в мілісекундах) було б встановлено мостовий паритет x64.


 

Для більш детальної інформації ознайомтеся зі статтею Покращення продуктивності ARM64 в .NET 7.

Покращена підтримка .NET на Linux

.NET 6 входить до складу Ubuntu 22.04 (Jammy) і може бути встановлена за допомогою команди apt install dotnet6. Крім того, існує оптимізований, заздалегідь створений, надмалий образ контейнера, який можна використовувати з коробки.

Щоб дізнатися більше про наше партнерство з Canonical та ARM, читайте .NET 6 тепер в Ubuntu 22.04.

64-розрядна підтримка IBM Power

На додаток до архітектури x64 (64-розрядні Intel/AMD), ARM64 (64-bit ARM) і s390× (64-bit IBM Z), .NET тепер також доступний для архітектури ppc64le (64-bit IBM Power), орієнтованої на RHEL 8.7 і RHEL 9.1.

 

Завдяки можливості працювати на Power, понад 25 000 клієнтів IBM Power можуть консолідувати наявні програми .NET на Windows x86 для запуску на тій самій платформі Power, що і їхні бізнес-додатки та бази даних на IBM і та AIX. Це може значно покращити екологічність завдяки зменшенню вуглецевого сліду в 5 разів у поєднанні з локальним масштабуванням RHEL та OpenShift, забезпечуючи при цьому найкращий у галузі наскрізний захист транзакцій та даних підприємства.

2. Сучасні

 

.NET 7 створено для сучасних хмарних додатків, мобільних клієнтів, периферійних сервісів та десктопних технологій. Створюйте мобільні додатки, використовуючи єдину кодову базу без шкоди для нативної продуктивності за допомогою інтерфейсу .NET MAUI. Створюйте адаптивні односторінкові додатки (SPA), які працюють у браузері та в автономному режимі як прогресивні веб-додатки (PWA), використовуючи знайомі технології, такі як шаблони C# та Razor. Ці швидкі сучасні можливості призначені не лише для нових додатків. Помічник з оновлення .NET надасть інформацію про сумісність, а в деяких випадках повністю перенесе ваші програми на .NET 6 і .NET 7.

.NET MAUI

NET MAUI тепер є частиною .NET 7 з безліччю покращень та нових функцій. Ви можете дізнатися про .NET MAUI й про те, як вона дозволяє створювати додатки для всіх мобільних пристроїв, прочитавши останнє повідомлення в блозі про .NET MAUI.

Blazor

 

Blazor продовжує розвиватися, і .NET 7 містить багато значних покращень. Тепер Blazor підтримує обробку подій зміни місцеперебування, покращено налагодження WebAssembly та вбудовано підтримку автентифікації за допомогою OpenID Connect. Щоб дізнатися більше, прочитайте останні записи в блозі команди Blazor.

Помічник з оновлення

Помічник з оновлення .NET надає покрокові вказівки, інформацію та автоматизацію для перенесення ваших застарілих програм на .NET 6 і .NET 7. У деяких випадках він може виконати міграцію за вас! Це допомагає скоротити час і складність при модернізації старих кодових баз. Наприклад, дізнайтеся, як перенести свої WCF-додатки на .NET Core за допомогою CoreWCF.

 З .NET 7 ви отримаєте наступні покращення:

 

  • ASP.NET на ASP.NET Core
  • System.Web адаптери (попередній перегляд)
  • Інкрементні міграції (попередній перегляд)
  • Додано більше аналізаторів та виправлень коду для WinForms, WPF та бібліотек консолей/класів
  • Вміння аналізувати двійкові файли
  • Підтримка UWP для Windows App SDK та WinUI

Готові перенести свій додаток на найновішу та найшвидшу на сьогодні .NET? Завантажте помічник з оновлення вже сьогодні!

Основні моменти міграції .NET 6

 

Після того, як минулого року було оголошено про вихід .NET 6, відбулося багато успішних переходів на останню версію .NET. Ці історії висвітлюють переваги значного покращення використання процесора, збільшення кількості запитів в секунду (RPS), кращого використання пулу потоків, зменшення розміру бінарних файлів, швидшого запуску, спрощеного управління залежностями, зменшення майбутнього технічного боргу, зниження витрат на інфраструктуру і, що найважливіше, – задоволення від роботи та продуктивності інженерів.

Подорож Azure Cosmos DB до .NET 6

Microsoft Exchange Online Подорож до ядра .NET

Подорож OneService до .NET 6

Подорож Microsoft Graph до .NET 6

Microsoft переходить від “середнього рівня” до ядра .NET

Подорож інфраструктури Microsoft Team та комунікаційних служб Azure до .NET 6

Платформа для рекламних кампаній Bing Ads Подорож до .NET 6

 

Подорож Stack Overflow до .NET 6

3. .NET для хмарних додатків

 

NET 7 спрощує створення хмарних додатків з нуля. Використовуйте підключені служби Visual Studio для безпечного підключення до служби даних і надійного шифрування рядків з’єднання у  секретних файлах користувача або сховищі Azure Key Vault. Створюйте свій додаток безпосередньо в образі контейнера. Використовуйте Entity Framework 7 для написання строго типізованих запитів Language Integrated Query (LINQ), які використовують підтримку JSON SQL Server для швидкого вилучення вмісту з JSON-документів, що зберігаються у вашій реляційній базі даних. Доставляйте захищені JSON-документи через автентифіковані кінцеві точки, використовуючи лише кілька рядків коду з мінімальним досвідом роботи з API. Отримуйте інформацію про запущений додаток за допомогою Open Telemetry.

Підтримка Azure в перший день роботи

.NET 7 не тільки чудово підходить для створення хмарних додатків; такі PaaS-сервіси Azure, як App Service для Windows і Linux, Static Web Apps, Azure Functions і Azure Container Apps, вже третій випуск поспіль готові до роботи з .NET 7, як і .NET 5.0 і 6.0. Протягом першого тижня після релізу ви можете зіткнутися з дещо довшим часом запуску додатків .NET 7, оскільки пакет .NET 7 SDK буде інстальовано вчасно для клієнтів, які створюють нові служби додатків з використанням .NET 7. Крім того, якщо ви використовували попередню версію .NET 7, просто перезапустивши службу додатків, ви оновите її до бітів GA.

Вбудована підтримка контейнерів

Популярність і практичне використання контейнерів зростає, і для багатьох компаній вони є найкращим способом розгортання в хмарі. Однак робота з контейнерами додає команді нових завдань, включаючи створення та публікацію образів, перевірку безпеки та відповідності вимогам, а також оптимізацію продуктивності образів. Вважається, що існує можливість створити кращий та більш спрощений досвід роботи з контейнерами .NET.

Тепер ви можете створювати контейнерні версії своїх додатків за допомогою простої публікації в dotnet. Це рішення створено з метою його безперешкодної інтеграції з наявною логікою побудови, використовуючи переваги власного багатого інструментарію C# та продуктивності під час виконання, а також вбудовано його прямо в коробку .NET SDK для регулярних оновлень.

Зображення контейнерів тепер є підтримуваним типом вихідних даних у .NET SDK:

 

Щоб дізнатися більше про підтримку вбудованих контейнерів, див. статтю Оголошення про підтримку вбудованих контейнерів для .NET SDK.

Microsoft Orleans

Microsoft Orleans 7.0 пропонує простішу модель програмування з “простими старими об’єктами CLR” (POCO), забезпечує до 150% кращу продуктивність, ніж 3.x, та впроваджує нові покращення серіалізації та незмінності. Розробники ASP.NET Core можуть легко додавати розподілені стани, використовуючи Orleans, і бути впевненими, що їхні додатки будуть масштабуватися горизонтально без додаткових складнощів.  Завдяки підтримці більшості популярних механізмів зберігання та баз даних, а також можливості запуску в будь-якому місці, де може працювати ASP.NET Core, Orleans є чудовим вибором для надання вашим .NET додаткам розподілених хмарних можливостей без необхідності вивчення нового фреймворку або набору інструментів. Дізнайтеся більше про Orleans 7.

Представляємо Activity.Current Change Event

Типова реалізація розподіленого трасування використовує AsyncLocal для відстеження “контексту діапазону” керованих потоків. Зміни контексту діапазону відстежуються за допомогою конструктора AsyncLocal, який приймає параметр valueChangedHandler. Однак, оскільки Activity стає стандартом для представлення діапазонів у OpenTelemetry, неможливо встановити обробник зміни значення, оскільки контекст відстежується за допомогою Activity.Current. Замість цього можна використовувати нову подію зміни для отримання бажаних сповіщень.

Показ методів перерахування властивостей продуктивної діяльності

Наступні нові методи можна використовувати у критичних до продуктивності сценаріях для перерахування властивостей Activity‘s Tags, Links, і Events без додаткових розподілів і доступу до елементів виконавця:

Показ методів перерахування властивостей продуктивної діяльності

Наступні нові методи можна використовувати у критичних до продуктивності сценаріях для перерахування властивостей Activity‘s Tags, Links, і Events без додаткових розподілів і доступу до елементів виконавця:

Виявлення ефективних методів тегів ActivityEvent і ActivityLink Enumerator

Подібно до вищесказаного, об’єкти ActivityEvent та ActivityLink Tag також відкриті, щоб зменшити будь-які зайві виділення для доступу до елементів виконавця:

4. Прості

C# 11 & F# 7

Новітніми версіями мов C# та F# є C# 11 та F# 7. C# 11 робить можливими нові функції, такі як узагальнена математика, а також спрощує ваш код завдяки покращеній ініціалізації об’єктів, необробленим рядковим літералам та багато чому іншому.

Загальна математика

У .NET 7 до бібліотеки базових класів додано нові узагальнені інтерфейси, пов’язані з математикою. Наявність цих інтерфейсів означає, що ви можете обмежити параметр типу узагальненого типу або методу, щоб він був “числовим”. Крім того, C# 11 і новіші версії дозволяють визначати статичні віртуальні члени інтерфейсу. Оскільки оператори мають бути оголошені як статичні, ця нова можливість C# дозволяє оголошувати оператори у нових інтерфейсах для числових типів.

Разом ці нововведення дозволяють виконувати математичні операції узагальнено – тобто без необхідності знати точний тип, з яким ви працюєте. Наприклад, якщо ви хотіли написати метод, який додає два числа, раніше вам доводилося додавати перевантаження методу для кожного типу (наприклад, static int Add(int first, int second) і static float Add(float first, float second)). Тепер ви можете написати один загальний метод, де параметр типу має бути тільки числовим типом.

У цьому методі параметр типу T має бути типом, який реалізує новий інтерфейс INumber. INumber реалізує інтерфейс IAdditionOperators, який містить +operator. Це дозволяє методу узагальнено додавати два числа. Метод можна використовувати з будь-яким вбудованим числовим типом .NET, оскільки всі вони були оновлені для реалізації INumber у .NET 7.

Автори бібліотек отримають найбільшу користь від узагальнених математичних інтерфейсів, оскільки вони зможуть спростити свою кодову базу, прибравши “надлишкові” перевантаження. Інші розробники отримають непряму вигоду, оскільки API, які вони використовують, можуть почати підтримувати більше типів.

 

Ознайомтеся з документацією на Generic Math для отримання додаткової інформації про основні API, що надаються кожним інтерфейсом.

Необроблені рядкові літерали

 

З’явився новий формат для рядкових літералів. Рядкові літерали можуть містити довільний текст, включаючи пробіли, нові рядки, вбудовані лапки та інші спеціальні символи, і не потребують екранування. Необроблений рядковий літерал починається щонайменше з трьох символів у подвійних лапках (“”“) і закінчується такою ж кількістю символів у подвійних лапках.

Бібліотеки .NET

 

Багато бібліотек .NET зазнали значних покращень у випуску .NET 7. Ви побачите підтримку анотацій, які можна зануляти, для пакетів Microsoft.Extensions.*, налаштування контрактів та ієрархії типів для System.Text.Json, нові API-інтерфейси Tar, які допоможуть вам записувати дані у форматі стрічкового архіву (TAR), і багато іншого.

Анотації для Microsoft.Extensions з нульовим значенням

Всі бібліотеки Microsoft.Extensions.* тепер містять опцію C# 8, яка дозволяє компілятору відстежувати можливість нульового типу посилань, щоб перехоплювати потенційні нульові роз’єднання посилань. Це допоможе вам мінімізувати ймовірність того, що ваш код призведе до виникнення виключення System.NullReferenceException.

System.Composition.Hosting

Додано новий API, який дозволяє створювати один екземпляр об’єкта в контейнері System.Composition.Hosting, надаючи функціональність, подібну до застарілих інтерфейсів System.ComponentModel.Composition.Hosting, через API ComposeExportedValue(CompositionContainer, T).

Додавання мікросекунд і наносекунд до міток часу, дати, зсуву дати та часу і лише часу

 

До .NET 7 найменшим кроком часу, доступним у різних структурах дати і часу, був ”tick“, доступний у властивості Ticks. Для довідки, один ”tick“ дорівнює 100 нс. Розробникам традиційно доводилося виконувати обчислення над значенням ”tick“ для визначення мікросекундних і наносекундних значень. У .NET 7 додали мікросекунди та наносекунди до реалізацій дати та часу:

Microsoft.Extensions.Caching

Було додано підтримку метрик для IMemoryCache, який є новим API MemoryCacheStatistics, що зберігає кеш-звернення, пропуски та оцінювальний розмір для IMemoryCache. Ви можете отримати екземпляр MemoryCacheStatistics за допомогою виклику GetCurrentStatistics() при увімкненому прапорці TrackStatistics.

API GetCurrentStatistics() дозволяє розробникам додатків використовувати лічильники подій або API метрик для відстеження статистики для одного або декількох кешів пам’яті.

Ви можете переглянути статистику нижче за допомогою інструменту  dotnet-counters:

System.Formats.Tar APIs

Було додано нову збірку System.Formats.Tar, яка містить кросплатформні API, що дозволяють читати, записувати, архівувати та розпаковувати Tar-архіви. Ці API навіть використовуються SDK для створення контейнерів для публікації.

Перетворювачі типу

 

Додано відкриті перетворювачі типів для нових примітивів DateOnly, TimeOnly, Int128, UInt128 та Half.

Це корисні конвертери для легкого перетворення в більш примітивні типи.

Налаштування контракту System.Text.Json

System.Text.Json визначає спосіб серіалізації та десеріалізації певного типу .NET шляхом створення контракту JSON для цього типу. Контракт створюється на основі форми типу – таких як доступні конструктори, властивості та поля, а також те, чи реалізує він IEnumerable або IDictionary - або під час виконання за допомогою рефлексії, або під час компіляції за допомогою генератора вихідного коду. У попередніх версіях користувачі могли вносити обмежені зміни до похідного контракту за допомогою анотацій атрибутів System.Text.Json, за умови, що вони можуть змінювати оголошення типу.

Метадані контракту для заданого типу T представлені за допомогою JsonTypeInfo, який у попередніх версіях слугував непрозорим токеном, що використовувався виключно в API генератора вихідного коду. Починаючи з .NET 7, більшість аспектів метаданих контракту JsonTypeInfo було відкрито і зроблено доступними для модифікації користувачем. Налаштування контрактів дозволяє користувачам писати власну логіку вирішення контрактів JSON за допомогою реалізації інтерфейсу IJsonTypeInfoResolver:

Резолвер контракту повертає сконфігурований екземпляр JsonTypeInfo для заданої комбінації Type і JsonSerializerOptions. Він може повернути null , якщо резолвер не підтримує метадані для вказаного типу вхідних даних.

Розв’язання контрактів, що виконується за замовчуванням серіалізатором на основі рефлексії, тепер доступне через клас DefaultJsonTypeInfoResolver, який реалізує IJsonTypeInfoResolver. Цей клас дозволяє користувачам розширювати стандартне розв’язання на основі рефлексії за допомогою власних модифікацій або комбінувати його з іншими резолверами (наприклад, згенерованими джерелом).

Починаючи з .NET 7 клас JsonSerializerContext, що використовується у генерації джерел, також реалізує IJsonTypeInfoResolver. Щоб дізнатися більше про генератор джерел, див. статтю Як використовувати генерацію джерел у System.Text.Json.

Екземпляр JsonSerializerOptions можна налаштувати з власним резолвером за допомогою нової властивості TypeInfoResolver:

Детальніше про налаштування контрактів читайте в статті [Що нового в System.Text.Json в .NET 7].