День 2446. #Карьера
Не Только Код: Что Делает Тебя Сеньором. Начало
Вы замечали, что на собеседованиях на старшие должности вас всё меньше гоняют по техническим вопросам? Вместо этого спрашивают что-то вроде: «Что такое технический долг?» Или «Что вы делаете, когда сроки срываются? Как расставляете приоритеты в задачах?» Быть сеньором не значит освоить каждый протокол или запомнить каждый алгоритм. Это рассудительность, работа с людьми, принятие решений, долгосрочное мышление. За годы опыта вы совершаете ошибки, и хорошо, если извлекаете из них уроки. Рассмотрим некоторые наиболее важные уроки на пути к сеньорской должности. Будем использовать вымышленного персонажа Эдди.
1. Рассуждения важнее правил
Однажды нам нужно было добавить новые поля в таблицу DynamoDB в рабочей среде. Эдди, блестящий джун, предложил тяжёлую миграцию: реплицировать таблицу, синхронизировать её с потоками, а затем, после недели тестирования, выполнить переход. План казался исчерпывающим, но он не рассматривал более простые варианты. Почему не обновить существующие записи с помощью скрипта? «Это опасно. Нельзя обновлять данные БД в проде», - воскликнул Эдди, без каких-либо обоснований или данных. Но в этой системе БД всего лишь обеспечивала работу офлайн-заданий, поэтому риск был невелик.
Подход Эдди отражал распространённую ловушку: воспринимать «лучшие практики» как абсолютную истину. «Никогда не трогайте прод». «Микросервисы всегда лучше монолита». Правила кажутся безопасными, но они зависят от контекста. Опытный разработчик - не тот, у которого в арсенале обширный набор правил. Он всегда старается объяснить, почему решение имеет смысл в данной ситуации, и взвешивает риски и компромиссы.
2. Не делайте предположений, проверяйте
Когда системы выходят из строя, легко сделать поспешные выводы: «Должно быть, дело в БД», «Возможно, это новое развёртывание». Но предположения отнимают драгоценные часы, а когда прод лежит, каждая минута на счету. Лучшие инженеры не полагаются на догадки. Они доверяют данным и используют свой опыт, чтобы определить, где искать в первую очередь, но всегда проверяют. Настоящее мастерство не в «правильной догадке», а в дисциплине, позволяющей проверять логи, воспроизводить проблемы и просить коллег проверить работоспособность. Проверка решает проблемы быстрее и укрепляет доверие. Ничто не подрывает доверие быстрее, чем самоуверенное обвинение в чём-то неправильном.
3. Сомневайтесь в хороших новостях
Однажды Эдди на радостях воскликнул: «API работает на 20% быстрее после моих изменений!». Странно, его просили просто отрефакторить код. Это выглядело как победа, но, когда что-то выглядит слишком хорошо, чтобы быть правдой, так оно и есть. После анализа мы выяснили: он случайно удалил логику повторных попыток в наших нисходящих вызовах. За блестящими цифрами копились скрытые сбои.
Всегда относитесь к внезапным чудесам скептически. Когда показатели внезапно улучшаются, первым вопросом должен быть: «Что мы сломали?» Здоровый скептицизм не даёт праздновать ложные победы. Он подкрепляет истину: данные ценны, только когда вы понимаете, почему они возникли.
4. Механизм важнее благих намерений
«Мы просто не забудем сделать X» - это всегда исходит из благих намерений, но они не защищают системы. Люди отвлекаются, устают или поджимают сроки. Однажды критический инцидент произошёл из-за того, что кто-то забыл запустить скрипт после развёртывания. Дело не в невнимательности, а в хрупкости процесса. Самые сильные команды не полагаются на память или обещания. Автоматизированные проверки, конвейеры CI/CD, флаги функций, ревью кода — это не «приятные мелочи», а защитные барьеры. Вместо того, чтобы доверять кому-то ручной запуск скрипта, вы делаете скрипт частью процесса развёртывания.
Ведущие инженеры проектируют системы, где безопасный путь — это также и самый простой. Ошибки неизбежны. Сильную инженерную культуру определяет способность системы выявлять эти ошибки раньше, чем это сделают ваши клиенты.
Окончание следует…
Источник: https://levelup.gitconnected.com/beyond-the-code-lessons-that-make-you-senior-1ba44469aa42
Не Только Код: Что Делает Тебя Сеньором. Начало
Вы замечали, что на собеседованиях на старшие должности вас всё меньше гоняют по техническим вопросам? Вместо этого спрашивают что-то вроде: «Что такое технический долг?» Или «Что вы делаете, когда сроки срываются? Как расставляете приоритеты в задачах?» Быть сеньором не значит освоить каждый протокол или запомнить каждый алгоритм. Это рассудительность, работа с людьми, принятие решений, долгосрочное мышление. За годы опыта вы совершаете ошибки, и хорошо, если извлекаете из них уроки. Рассмотрим некоторые наиболее важные уроки на пути к сеньорской должности. Будем использовать вымышленного персонажа Эдди.
1. Рассуждения важнее правил
Однажды нам нужно было добавить новые поля в таблицу DynamoDB в рабочей среде. Эдди, блестящий джун, предложил тяжёлую миграцию: реплицировать таблицу, синхронизировать её с потоками, а затем, после недели тестирования, выполнить переход. План казался исчерпывающим, но он не рассматривал более простые варианты. Почему не обновить существующие записи с помощью скрипта? «Это опасно. Нельзя обновлять данные БД в проде», - воскликнул Эдди, без каких-либо обоснований или данных. Но в этой системе БД всего лишь обеспечивала работу офлайн-заданий, поэтому риск был невелик.
Подход Эдди отражал распространённую ловушку: воспринимать «лучшие практики» как абсолютную истину. «Никогда не трогайте прод». «Микросервисы всегда лучше монолита». Правила кажутся безопасными, но они зависят от контекста. Опытный разработчик - не тот, у которого в арсенале обширный набор правил. Он всегда старается объяснить, почему решение имеет смысл в данной ситуации, и взвешивает риски и компромиссы.
2. Не делайте предположений, проверяйте
Когда системы выходят из строя, легко сделать поспешные выводы: «Должно быть, дело в БД», «Возможно, это новое развёртывание». Но предположения отнимают драгоценные часы, а когда прод лежит, каждая минута на счету. Лучшие инженеры не полагаются на догадки. Они доверяют данным и используют свой опыт, чтобы определить, где искать в первую очередь, но всегда проверяют. Настоящее мастерство не в «правильной догадке», а в дисциплине, позволяющей проверять логи, воспроизводить проблемы и просить коллег проверить работоспособность. Проверка решает проблемы быстрее и укрепляет доверие. Ничто не подрывает доверие быстрее, чем самоуверенное обвинение в чём-то неправильном.
3. Сомневайтесь в хороших новостях
Однажды Эдди на радостях воскликнул: «API работает на 20% быстрее после моих изменений!». Странно, его просили просто отрефакторить код. Это выглядело как победа, но, когда что-то выглядит слишком хорошо, чтобы быть правдой, так оно и есть. После анализа мы выяснили: он случайно удалил логику повторных попыток в наших нисходящих вызовах. За блестящими цифрами копились скрытые сбои.
Всегда относитесь к внезапным чудесам скептически. Когда показатели внезапно улучшаются, первым вопросом должен быть: «Что мы сломали?» Здоровый скептицизм не даёт праздновать ложные победы. Он подкрепляет истину: данные ценны, только когда вы понимаете, почему они возникли.
4. Механизм важнее благих намерений
«Мы просто не забудем сделать X» - это всегда исходит из благих намерений, но они не защищают системы. Люди отвлекаются, устают или поджимают сроки. Однажды критический инцидент произошёл из-за того, что кто-то забыл запустить скрипт после развёртывания. Дело не в невнимательности, а в хрупкости процесса. Самые сильные команды не полагаются на память или обещания. Автоматизированные проверки, конвейеры CI/CD, флаги функций, ревью кода — это не «приятные мелочи», а защитные барьеры. Вместо того, чтобы доверять кому-то ручной запуск скрипта, вы делаете скрипт частью процесса развёртывания.
Ведущие инженеры проектируют системы, где безопасный путь — это также и самый простой. Ошибки неизбежны. Сильную инженерную культуру определяет способность системы выявлять эти ошибки раньше, чем это сделают ваши клиенты.
Окончание следует…
Источник: https://levelup.gitconnected.com/beyond-the-code-lessons-that-make-you-senior-1ba44469aa42
👍30
День 2447. #Карьера
Не Только Код: Что Делает Тебя Сеньором. Окончание
Начало
5. Дисциплина отказа
Однажды Эдди был на встрече с одним из клиентов. Они использовали наши API и хотели внедрить новую логику фильтрации. Вместо того, чтобы реализовывать её на своей стороне, они предложили сделать это на нашем бэкенде. Они убедили Эдди согласиться. Но когда он поделился решением с командой, все ведущие инженеры выразили несогласие. У клиентов не было веских причин так делать, они просто хотели переложить всю сложность на нас.
Это один из самых сложных уроков в карьере. Сеньоры не из тех, кто на всё отвечает «да». Они защищают свои команды от ненужной сложности, отвергают бессмысленные компромиссы, и понимают, что не каждый запрос заслуживает одобрения.
6. Рост начинается с ответственности
В начале карьеры мы во многом полагаемся на старших коллег. Но инженерия полна неопределённости. Старшие коллеги — не те, кто всегда знает правильный ответ; они принимают обоснованные решения, взвешивают компромиссы и берут на себя ответственность. Когда эти решения оказываются неправильными, они не перекладывают вину на других, а принимают последствия, учатся и корректируют свои действия.
7. От защитника к наставнику
Естественным инстинктом является оградить младших коллег от неудач. Оставлять длинные комментарии, объяснять каждую деталь или даже исправлять их код. Это может предотвратить сиюминутные трудности, но также лишает их возможности извлекать уроки, которые можно извлечь только из личного опыта.
Роль сеньора не в предотвращении ошибок, а в создании безопасного пространства, где ошибки могут происходить без катастрофических последствий. Настоящий рост достигается благодаря ошибкам, восстановлению и дальнейшему развитию. Высший показатель лидерства — способность команды процветать без вас. Если вы создали культуру, в которой люди учатся на безопасных ошибках, то вы выполнили свою задачу наставника.
8. Простота масштабируется, сложность ломается
Сделать просто почти всегда лучше, чем заумно. Иногда возникает соблазн проектировать систему с учётом всех возможных сценариев, «закладывая фундамент» в будущее с помощью абстракций и расширяемости. Но чаще всего эти дополнительные уровни превращаются в мёртвый груз. Старайтесь избегать преждевременной сложности любой ценой. Простые решения не только проще писать, но и легче тестировать, поддерживать и адаптировать к ним новых разработчиков.
9. Каждая система рано или поздно ломается, будьте готовы
Ни одна система не является по-настоящему отказоустойчивой. Код живой: он развивается, интегрируется с новыми зависимостями и адаптируется к меняющимся требованиям. Каждое изменение, каким бы небольшим и хорошо протестированным оно ни было, увеличивает вероятность возникновения сбоев. Сеньоры предвидят это, чётко соблюдая гарантии, тщательно контролируя версии API и настраивая мониторинг и т.п. Тесты ценны, но не являются панацеей. При достаточном времени, достаточном трафике и достаточном количестве изменений любая система выйдет из строя. Вопрос - когда и насколько вы готовы к этому.
10. Принимайте изменения и адаптируйтесь
Изменения постоянны, и их темп только ускоряется. Сейчас LLM уже стали частью повседневных рабочих процессов. Есть ли вокруг них хайп? Да. Но было бы ошибкой предполагать, что они просто исчезнут, а мы станем работать по старинке. Они продолжат совершенствоваться и постепенно брать на себя всё больше ответственности.
Мы ещё в начале пути к пониманию долгосрочного влияния LLM. Но уже понятно, что они не заменят инженерное суждение, а при разумном использовании могут ускорить процесс.
Поэтому принятие изменений не означает слепого доверия к коду, сгенерированному ИИ, и не предполагает, что он решит все проблемы. Это означает быть в курсе событий, осторожно экспериментировать и интегрировать то, что действительно приносит пользу, учитывая риски.
Источник: https://levelup.gitconnected.com/beyond-the-code-lessons-that-make-you-senior-1ba44469aa42
Не Только Код: Что Делает Тебя Сеньором. Окончание
Начало
5. Дисциплина отказа
Однажды Эдди был на встрече с одним из клиентов. Они использовали наши API и хотели внедрить новую логику фильтрации. Вместо того, чтобы реализовывать её на своей стороне, они предложили сделать это на нашем бэкенде. Они убедили Эдди согласиться. Но когда он поделился решением с командой, все ведущие инженеры выразили несогласие. У клиентов не было веских причин так делать, они просто хотели переложить всю сложность на нас.
Это один из самых сложных уроков в карьере. Сеньоры не из тех, кто на всё отвечает «да». Они защищают свои команды от ненужной сложности, отвергают бессмысленные компромиссы, и понимают, что не каждый запрос заслуживает одобрения.
6. Рост начинается с ответственности
В начале карьеры мы во многом полагаемся на старших коллег. Но инженерия полна неопределённости. Старшие коллеги — не те, кто всегда знает правильный ответ; они принимают обоснованные решения, взвешивают компромиссы и берут на себя ответственность. Когда эти решения оказываются неправильными, они не перекладывают вину на других, а принимают последствия, учатся и корректируют свои действия.
7. От защитника к наставнику
Естественным инстинктом является оградить младших коллег от неудач. Оставлять длинные комментарии, объяснять каждую деталь или даже исправлять их код. Это может предотвратить сиюминутные трудности, но также лишает их возможности извлекать уроки, которые можно извлечь только из личного опыта.
Роль сеньора не в предотвращении ошибок, а в создании безопасного пространства, где ошибки могут происходить без катастрофических последствий. Настоящий рост достигается благодаря ошибкам, восстановлению и дальнейшему развитию. Высший показатель лидерства — способность команды процветать без вас. Если вы создали культуру, в которой люди учатся на безопасных ошибках, то вы выполнили свою задачу наставника.
8. Простота масштабируется, сложность ломается
Сделать просто почти всегда лучше, чем заумно. Иногда возникает соблазн проектировать систему с учётом всех возможных сценариев, «закладывая фундамент» в будущее с помощью абстракций и расширяемости. Но чаще всего эти дополнительные уровни превращаются в мёртвый груз. Старайтесь избегать преждевременной сложности любой ценой. Простые решения не только проще писать, но и легче тестировать, поддерживать и адаптировать к ним новых разработчиков.
9. Каждая система рано или поздно ломается, будьте готовы
Ни одна система не является по-настоящему отказоустойчивой. Код живой: он развивается, интегрируется с новыми зависимостями и адаптируется к меняющимся требованиям. Каждое изменение, каким бы небольшим и хорошо протестированным оно ни было, увеличивает вероятность возникновения сбоев. Сеньоры предвидят это, чётко соблюдая гарантии, тщательно контролируя версии API и настраивая мониторинг и т.п. Тесты ценны, но не являются панацеей. При достаточном времени, достаточном трафике и достаточном количестве изменений любая система выйдет из строя. Вопрос - когда и насколько вы готовы к этому.
10. Принимайте изменения и адаптируйтесь
Изменения постоянны, и их темп только ускоряется. Сейчас LLM уже стали частью повседневных рабочих процессов. Есть ли вокруг них хайп? Да. Но было бы ошибкой предполагать, что они просто исчезнут, а мы станем работать по старинке. Они продолжат совершенствоваться и постепенно брать на себя всё больше ответственности.
Мы ещё в начале пути к пониманию долгосрочного влияния LLM. Но уже понятно, что они не заменят инженерное суждение, а при разумном использовании могут ускорить процесс.
Поэтому принятие изменений не означает слепого доверия к коду, сгенерированному ИИ, и не предполагает, что он решит все проблемы. Это означает быть в курсе событий, осторожно экспериментировать и интегрировать то, что действительно приносит пользу, учитывая риски.
Источник: https://levelup.gitconnected.com/beyond-the-code-lessons-that-make-you-senior-1ba44469aa42
👍30
День 2448. #ЗаметкиНаПолях
Использование Токенов Отмены
Сегодня посмотрим, почему стоит использовать токены отмены в вашем API. Дело не только в вашем коде.
Представьте, что у нас есть длительный SQL-запрос, например:
Конечно, это всего лишь «бесполезный» демонстрационный код, но идея в том, что он выполняется долго и может значительно нагружать процессор, память и ввод-вывод. Если это часть вашего (REST) API и HTTP-запрос отменяется, SQL-запрос всё равно продолжит выполняться.
Вы можете легко проверить это с помощью:
И вы увидите, что этот запрос выполняется, даже если вызов REST прерывается. При завершении консольного приложения этого не произойдёт, т.к. это приведет к прерыванию соединения с БД и транзакции.
Теперь, если мы предоставим токен отмены:
Теперь, если запустить тот же запрос к sys.dm_exec_requests, вы увидите, что после отмены, сервер также прерывает и SQL-запрос.
Так ваш код не только лучше масштабируется, поскольку может освобождать ненужные ресурсы, но и, если внешняя система также поддерживает это, она также может экономить ресурсы.
В этом примере это был SQL-сервер, который реагировал на отмену. Но если вы также передадите токен отмены в HttpClient, это прервёт запрос, и другая сторона может отреагировать таким же образом. См. Отмена Операции при Отмене HTTP Запроса.
Не факт, что это поддерживают все технологии. Похоже, что, например, провайдер для Postgresql это поддерживает. Так что технически это возможно, но опыт может отличаться. В любом случае, добавление токена — хорошая практика, поскольку поставщики могут улучшить поддержку в будущем.
Всегда ли нужно предоставлять токен отмены?
Если вы видите в вопросе слова «всегда» или «никогда», ответ, скорее всего, «нет». Конечно, общее правило — добавлять токен отмены к вызовам, которые его поддерживают, но давайте посмотрим на следующий код:
Представьте, что пользователь отменяет запрос, во время сохранения адреса. Пользователь добавляется, а адрес и роль — нет. Теперь вы находитесь в несогласованном состоянии. Конечно, этот пример надуманный. Простое решение — вызвать SaveChangesAsync только один раз в конце или использовать транзакцию, которая фиксируется в конце один раз. Но иногда у вас есть сторонний код, который также хранит информацию где-то, где вы не можете её контролировать. Поэтому нужно убедиться, что вы не столкнётесь с несогласованными состояниями из-за того, что кто-то прервал запрос!
Источник: https://steven-giesel.com/blogPost/080baaef-27d4-4d98-b0a8-9c3ab96c335e/use-cancellationtokens
Использование Токенов Отмены
Сегодня посмотрим, почему стоит использовать токены отмены в вашем API. Дело не только в вашем коде.
Представьте, что у нас есть длительный SQL-запрос, например:
-- MSSQL
SELECT COUNT_BIG(*)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
CROSS JOIN sys.all_objects c
CROSS JOIN sys.all_objects d
CROSS JOIN sys.all_objects e;
Конечно, это всего лишь «бесполезный» демонстрационный код, но идея в том, что он выполняется долго и может значительно нагружать процессор, память и ввод-вывод. Если это часть вашего (REST) API и HTTP-запрос отменяется, SQL-запрос всё равно продолжит выполняться.
Вы можете легко проверить это с помощью:
SELECT * FROM sys.dm_exec_requests WHERE status = 'running';
И вы увидите, что этот запрос выполняется, даже если вызов REST прерывается. При завершении консольного приложения этого не произойдёт, т.к. это приведет к прерыванию соединения с БД и транзакции.
Теперь, если мы предоставим токен отмены:
using var cts =
new CancellationTokenSource(TimeSpan.FromSeconds(2));
try
{
await dbContext.Database.ExecuteSqlAsync(
$"""
SELECT COUNT_BIG(*)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
CROSS JOIN sys.all_objects c
CROSS JOIN sys.all_objects d
CROSS JOIN sys.all_objects e;
""", cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Запрос отменён!");
}
Теперь, если запустить тот же запрос к sys.dm_exec_requests, вы увидите, что после отмены, сервер также прерывает и SQL-запрос.
Так ваш код не только лучше масштабируется, поскольку может освобождать ненужные ресурсы, но и, если внешняя система также поддерживает это, она также может экономить ресурсы.
В этом примере это был SQL-сервер, который реагировал на отмену. Но если вы также передадите токен отмены в HttpClient, это прервёт запрос, и другая сторона может отреагировать таким же образом. См. Отмена Операции при Отмене HTTP Запроса.
Не факт, что это поддерживают все технологии. Похоже, что, например, провайдер для Postgresql это поддерживает. Так что технически это возможно, но опыт может отличаться. В любом случае, добавление токена — хорошая практика, поскольку поставщики могут улучшить поддержку в будущем.
Всегда ли нужно предоставлять токен отмены?
Если вы видите в вопросе слова «всегда» или «никогда», ответ, скорее всего, «нет». Конечно, общее правило — добавлять токен отмены к вызовам, которые его поддерживают, но давайте посмотрим на следующий код:
var user = new User { Name = dto.Name };
db.Users.Add(user);
await _db.SaveChangesAsync(ct);
var address =
new Address { UserId = user.Id, City = dto.City };
db.Addresses.Add(address);
await _db.SaveChangesAsync(ct);
var role =
new Role { UserId = user.Id, Name = "Member" };
db.Roles.Add(role);
await _db.SaveChangesAsync(ct);Представьте, что пользователь отменяет запрос, во время сохранения адреса. Пользователь добавляется, а адрес и роль — нет. Теперь вы находитесь в несогласованном состоянии. Конечно, этот пример надуманный. Простое решение — вызвать SaveChangesAsync только один раз в конце или использовать транзакцию, которая фиксируется в конце один раз. Но иногда у вас есть сторонний код, который также хранит информацию где-то, где вы не можете её контролировать. Поэтому нужно убедиться, что вы не столкнётесь с несогласованными состояниями из-за того, что кто-то прервал запрос!
Источник: https://steven-giesel.com/blogPost/080baaef-27d4-4d98-b0a8-9c3ab96c335e/use-cancellationtokens
👍21
День 2449. #TipsAndTricks #Blazor
Лучшие Практики по Созданию Веб-Приложений в Blazor. Начало
Рассмотрим 9 рекомендаций по созданию веб-приложений Blazor.
1. Понимание жизненного цикла компонента
Первый и самый важный шаг при изучении Blazor — это правильное понимание жизненного цикла компонента. Blazor использует компонентно-ориентированную систему рендеринга, похожую на другие современные фреймворки веб-приложений, такие как Angular или React. См. подробнее о создании Blazor-компонентов.
Помимо изучения реализации компонентов Blazor, важно понимать, когда компонент Blazor автоматически перерисовывается и как управлять этим поведением. Например, мы можем переопределить метод жизненного цикла ShouldRender для управления обновлением UI. Если метод возвращает true, компонент перерисовывается.
2. Выбор правильного размера компонента
Одна из самых сложных задач - решение о том, когда следует разбить код на несколько компонентов. Нужно начать с простого. Сначала создаём маршрутизируемый компонент страницы и пишем весь код в нём. В какой-то момент код разрастается, и приходит понимание, что часть кода не связана с другой частью. Например, обработка формы никак не связана с отображением таблицы. Это сигнал, чтобы разделить компоненты, извлечь дочерние компоненты и превратить компонент страницы в оркестратор нескольких дочерних компонентов.
Не существует правильного или неправильного подхода, и требуется опыт, чтобы понять, что работает лучше всего. Одно из полезных правил - выделять то, что связано друг с другом, и ценить связность больше, чем размер (количество строк кода).
3. Реализация независимого режима рендеринга для Blazor-компонентов
С появлением интерактивного режима рендеринга в .NET 8 мы получаем гораздо больше гибкости по сравнению с предыдущими версиями Blazor. Например, мы можем реализовать веб-приложение, полностью отрисовываемое на сервере, без какой-либо интерактивности. Или можем комбинировать интерактивность Blazor Server и Blazor WebAssembly в одном приложении.
Для обеспечения гибкой архитектуры рекомендуется настроить компоненты Blazor так, чтобы они не зависели от режима рендеринга. Т.е. не задавать тип интерактивности внутри каждого компонента, а задавать его только на верхнем уровне. Это позволяет использовать компонент как часть интерактивного приложения Blazor Server и Blazor WebAssembly.
4. Изучите правильную обработку событий
Узнайте, как привязывать методы C# к событиям, вызываемым HTML-элементами. Это фундаментальный механизм для реализации обработчиков onClick для кнопок или обработчиков отправки для HTML-форм. При регистрации событий .NET, таких как событие LocationChanged класса NavigationManager, обязательно отписывайтесь от события при удалении компонента. В противном случае компонент не будет уничтожен сборщиком мусора.
Что касается связи между компонентами, обратные вызовы событий (EventCallback) являются стандартным способом осуществления обратного вызова родительского компонента из дочернего компонента.
Окончание следует…
Источник: https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications
Лучшие Практики по Созданию Веб-Приложений в Blazor. Начало
Рассмотрим 9 рекомендаций по созданию веб-приложений Blazor.
1. Понимание жизненного цикла компонента
Первый и самый важный шаг при изучении Blazor — это правильное понимание жизненного цикла компонента. Blazor использует компонентно-ориентированную систему рендеринга, похожую на другие современные фреймворки веб-приложений, такие как Angular или React. См. подробнее о создании Blazor-компонентов.
Помимо изучения реализации компонентов Blazor, важно понимать, когда компонент Blazor автоматически перерисовывается и как управлять этим поведением. Например, мы можем переопределить метод жизненного цикла ShouldRender для управления обновлением UI. Если метод возвращает true, компонент перерисовывается.
2. Выбор правильного размера компонента
Одна из самых сложных задач - решение о том, когда следует разбить код на несколько компонентов. Нужно начать с простого. Сначала создаём маршрутизируемый компонент страницы и пишем весь код в нём. В какой-то момент код разрастается, и приходит понимание, что часть кода не связана с другой частью. Например, обработка формы никак не связана с отображением таблицы. Это сигнал, чтобы разделить компоненты, извлечь дочерние компоненты и превратить компонент страницы в оркестратор нескольких дочерних компонентов.
Не существует правильного или неправильного подхода, и требуется опыт, чтобы понять, что работает лучше всего. Одно из полезных правил - выделять то, что связано друг с другом, и ценить связность больше, чем размер (количество строк кода).
3. Реализация независимого режима рендеринга для Blazor-компонентов
С появлением интерактивного режима рендеринга в .NET 8 мы получаем гораздо больше гибкости по сравнению с предыдущими версиями Blazor. Например, мы можем реализовать веб-приложение, полностью отрисовываемое на сервере, без какой-либо интерактивности. Или можем комбинировать интерактивность Blazor Server и Blazor WebAssembly в одном приложении.
Для обеспечения гибкой архитектуры рекомендуется настроить компоненты Blazor так, чтобы они не зависели от режима рендеринга. Т.е. не задавать тип интерактивности внутри каждого компонента, а задавать его только на верхнем уровне. Это позволяет использовать компонент как часть интерактивного приложения Blazor Server и Blazor WebAssembly.
4. Изучите правильную обработку событий
Узнайте, как привязывать методы C# к событиям, вызываемым HTML-элементами. Это фундаментальный механизм для реализации обработчиков onClick для кнопок или обработчиков отправки для HTML-форм. При регистрации событий .NET, таких как событие LocationChanged класса NavigationManager, обязательно отписывайтесь от события при удалении компонента. В противном случае компонент не будет уничтожен сборщиком мусора.
@implements IDisposable
@inject NavigationManager NavigationManager
protected override void OnInitialized()
{
NavigationManager.LocationChanged
+= LocationChanged;
}
void LocationChanged(
object sender,
LocationChangedEventArgs e)
{
System.WriteLine("Location changed");
}
void IDisposable.Dispose()
{
NavigationManager.LocationChanged
-= LocationChanged;
}
Что касается связи между компонентами, обратные вызовы событий (EventCallback) являются стандартным способом осуществления обратного вызова родительского компонента из дочернего компонента.
Окончание следует…
Источник: https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications
👍7
День 2450. #TipsAndTricks #Blazor
Лучшие Практики по Созданию Веб-Приложений в Blazor. Окончание
Начало
5. Выберите подходящий метод управления состоянием
Blazor предлагает различные варианты управления состоянием. Параметры компонентов — самый простой вариант, за которым следуют каскадные значения и извлечение состояния в специализированные реализации сервисов.
Для больших приложений может подойти библиотека управления состоянием, например, Fluxor, или другой контейнер глобального состояния. Однако имейте в виду, что обработка глобального состояния может привести к сложностям в приложении.
6. Правильная организация и структура кода
Используйте чёткую, понятную и организованную структуру кода. Например, группируйте связанные компоненты по папкам, а сервисы и страницы — в логические папки.
Также следуйте рекомендациям по именованию компонентов, таким как соглашения об именовании, и разделяйте задачи путём извлечения компонентов, чтобы повысить удобство поддержки всего приложения.
Новый шаблон веб-приложения Blazor в .NET 8 - хорошая отправная точка. Однако обязательно реорганизуйте код, когда приложение значительно разрастётся в той или иной области, чтобы не приходилось постоянно искать связанные части кода.
7. Защитите приложение
Ознакомьтесь с лучшими практиками веб-безопасности, такими как OSWASP Top 10, и примите меры, особенно при работе с конфиденциальными данными.
Используйте аутентификацию и авторизацию ASP.NET Core для защиты доступа к конечным точкам и страницам Blazor. Храните только ту информацию, которая необходима для выполнения ваших бизнес-задач. Всегда используйте HTTPS.
Не храните пароли пользователей самостоятельно. Используйте провайдер аутентификации. Если нет другого варианта и приходится хранить учётные записи пользователей самостоятельно, убедитесь, что пароли правильно хэшируются с помощью надежного алгоритма хэширования, например, BCrypt.
8. Используйте правильную обработку ошибок и ведение журнала
Реализуйте надёжное решение для обработки ошибок и исключений. Убедитесь, что логи содержат важную информацию для решения проблем в коде. В то же время избегайте регистрации конфиденциальной информации и заменяйте ее плейсхолдерами.
Вы можете использовать фреймворк логирования ASP.NET Core или добавить более гибкое и эффективное решение, например, Serilog.
9. Максимально простое решение
Один из самых недооценённых советов как в разработке ПО в целом, так и в разработке на Blazor — это простота. Существует множество сложных реализаций, которые можно заменить простыми решениями. Всегда стремитесь реализовать максимально простое решение любой задачи.
Например, когда нужно передать значение компоненту, начните с использования параметра компонента. Зачем реализовывать сложный сервис и внедрять его в дочерний компонент, если можно решить проблему с помощью простого параметра компонента?
Источник: https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications
Лучшие Практики по Созданию Веб-Приложений в Blazor. Окончание
Начало
5. Выберите подходящий метод управления состоянием
Blazor предлагает различные варианты управления состоянием. Параметры компонентов — самый простой вариант, за которым следуют каскадные значения и извлечение состояния в специализированные реализации сервисов.
Для больших приложений может подойти библиотека управления состоянием, например, Fluxor, или другой контейнер глобального состояния. Однако имейте в виду, что обработка глобального состояния может привести к сложностям в приложении.
6. Правильная организация и структура кода
Используйте чёткую, понятную и организованную структуру кода. Например, группируйте связанные компоненты по папкам, а сервисы и страницы — в логические папки.
Также следуйте рекомендациям по именованию компонентов, таким как соглашения об именовании, и разделяйте задачи путём извлечения компонентов, чтобы повысить удобство поддержки всего приложения.
Новый шаблон веб-приложения Blazor в .NET 8 - хорошая отправная точка. Однако обязательно реорганизуйте код, когда приложение значительно разрастётся в той или иной области, чтобы не приходилось постоянно искать связанные части кода.
7. Защитите приложение
Ознакомьтесь с лучшими практиками веб-безопасности, такими как OSWASP Top 10, и примите меры, особенно при работе с конфиденциальными данными.
Используйте аутентификацию и авторизацию ASP.NET Core для защиты доступа к конечным точкам и страницам Blazor. Храните только ту информацию, которая необходима для выполнения ваших бизнес-задач. Всегда используйте HTTPS.
Не храните пароли пользователей самостоятельно. Используйте провайдер аутентификации. Если нет другого варианта и приходится хранить учётные записи пользователей самостоятельно, убедитесь, что пароли правильно хэшируются с помощью надежного алгоритма хэширования, например, BCrypt.
8. Используйте правильную обработку ошибок и ведение журнала
Реализуйте надёжное решение для обработки ошибок и исключений. Убедитесь, что логи содержат важную информацию для решения проблем в коде. В то же время избегайте регистрации конфиденциальной информации и заменяйте ее плейсхолдерами.
Вы можете использовать фреймворк логирования ASP.NET Core или добавить более гибкое и эффективное решение, например, Serilog.
9. Максимально простое решение
Один из самых недооценённых советов как в разработке ПО в целом, так и в разработке на Blazor — это простота. Существует множество сложных реализаций, которые можно заменить простыми решениями. Всегда стремитесь реализовать максимально простое решение любой задачи.
Например, когда нужно передать значение компоненту, начните с использования параметра компонента. Зачем реализовывать сложный сервис и внедрять его в дочерний компонент, если можно решить проблему с помощью простого параметра компонента?
Источник: https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications
2👍5
День 2451. #Карьера
Я Разработчик Средних Лет, и Мои Лучшие Качества… Изменились
И то, что для меня важно, тоже изменилось.
Автор оригинала: Jeffrey Bakker
Языки, которые я использовал, платформы, на которых я работал, и решённые бизнес-задачи невероятно разнообразны. Мне нравится разработка функций, архитектура, покрытие кода, тестирование, CI/CD, UI и даже документация. Всё должно быть хорошо, так о чём же эта история?
Мой мозг изменился
В среднем возрасте мой технический фокус сместился. Я меньше одержим погоней за каждым новым инструментом и больше сосредоточен на глубине и ясности. Мой интеллект способен справиться с большей широтой, но мой фокус рассеян; я осознаю гораздо больше, о чём раньше не беспокоился. Я не запоминаю детали, как раньше, но быстрее связываю идеи и вижу закономерности, которые раньше упускал из виду.
Я обменял часть своих технических навыков на более «человеческие», и это открыло мне больше дверей. Мне приходится чаще использовать навыки общения. Как интроверта, любившего прятаться в своей работе, эта мысль раньше меня пугала.
Стало не хуже, просто по-другому
Хваля молодых разработчиков за их новые и захватывающие функции, я с теплотой скучаю по той же похвале, но не скучаю по давлению, которое часто с ней связано. Да, я всё ещё иногда работаю сверхурочно, но мне нравится делать это ради тех задач, которые мне нравятся.
Я бывал в центре внимания, но никогда не стремился к нему. Иногда рутинная работа сама по себе награда. Я всегда думаю о том, как помочь нашей команде. Мне бы хотелось работать над темой, которая соответствует моим средне- и долгосрочным карьерным целям, а не над темой месяца.
Мой золотой век был период с 2012 по 2019 год, охватывающий три софтверные корпорации. До этого я уже разрабатывал ПО типичными неправильными способами. Поначалу я отрицал и сопротивлялся некоторым передовым практикам (отвыкать от привычек сложно). Но в итоге я стал лучше, начал отстаивать все передовые практики. Меня слышали и уважали, потому что я добился успеха. Несколько лет спустя я выгорел, пытаясь изменить компанию, которая находилась в таком же состоянии отрицания, что и я сам несколько лет назад.
Мне не нужно переживать прошлое
Каждый из нас вспоминал времена, когда всё шло идеально. Спустя десять лет работы сеньором, я могу сказать, что я-«молодой сеньор», много знал о технологиях, но мало о людях и корпорациях. Я мог действовать самостоятельно, когда позволяли, но моё видение ограничивалось тем, что мне было позволено видеть. Я был способным и всесторонне развитым технически, но в бизнесе у меня был эффект Даннинга-Крюгера.
Что меня ждёт в будущем?
Лет 10 назад один из моих тимлидов углубился в управление персоналом, признав, что он «слишком стар, чтобы идти в ногу с новейшими технологиями и практиками». Другой менеджер, наоборот, сказал, что выбрал менеджмент, потому что разработка со временем стала скучной. Ему нужен был новый вызов.
Я всегда думал, что пойду по пути техлида. Но я оставил стек, на котором специализировался несколько лет. Сейчас я вряд ли могу продемонстрировать какие-либо лидерские качества в текущем стеке. DevOps выглядит привлекательно, поскольку соответствует тому, что я считаю важным. Хотя я бы скучал по временам, когда был и разработчиком функций, и тестировщиком, и DevOpsом.
Итого
У меня была полноценная карьера. Я не сияю так ярко, как раньше, но я стал мудрее. Молодым разработчикам есть на что опереться, чтобы они могли сиять. Никогда ещё технологии разработки ПО не были так многослойны и многообразны. Работа с современными языками программирования может доставлять удовольствие. Мы достаточно раз терпели неудачи, чтобы показать вам, что не работает, и у нас достаточно примеров того, что работает стабильно. Ваша главная задача сейчас — выделяться. Сияйте ярко!
PS: Напишите в комментариях, как изменились ваши приоритеты в карьере с течением времени.
Источник: https://levelup.gitconnected.com/im-a-middle-aged-developer-and-my-time-to-shine-has-sunset-a1b5d5c6ff2d
Я Разработчик Средних Лет, и Мои Лучшие Качества… Изменились
И то, что для меня важно, тоже изменилось.
Автор оригинала: Jeffrey Bakker
Языки, которые я использовал, платформы, на которых я работал, и решённые бизнес-задачи невероятно разнообразны. Мне нравится разработка функций, архитектура, покрытие кода, тестирование, CI/CD, UI и даже документация. Всё должно быть хорошо, так о чём же эта история?
Мой мозг изменился
В среднем возрасте мой технический фокус сместился. Я меньше одержим погоней за каждым новым инструментом и больше сосредоточен на глубине и ясности. Мой интеллект способен справиться с большей широтой, но мой фокус рассеян; я осознаю гораздо больше, о чём раньше не беспокоился. Я не запоминаю детали, как раньше, но быстрее связываю идеи и вижу закономерности, которые раньше упускал из виду.
Я обменял часть своих технических навыков на более «человеческие», и это открыло мне больше дверей. Мне приходится чаще использовать навыки общения. Как интроверта, любившего прятаться в своей работе, эта мысль раньше меня пугала.
Стало не хуже, просто по-другому
Хваля молодых разработчиков за их новые и захватывающие функции, я с теплотой скучаю по той же похвале, но не скучаю по давлению, которое часто с ней связано. Да, я всё ещё иногда работаю сверхурочно, но мне нравится делать это ради тех задач, которые мне нравятся.
Я бывал в центре внимания, но никогда не стремился к нему. Иногда рутинная работа сама по себе награда. Я всегда думаю о том, как помочь нашей команде. Мне бы хотелось работать над темой, которая соответствует моим средне- и долгосрочным карьерным целям, а не над темой месяца.
Мой золотой век был период с 2012 по 2019 год, охватывающий три софтверные корпорации. До этого я уже разрабатывал ПО типичными неправильными способами. Поначалу я отрицал и сопротивлялся некоторым передовым практикам (отвыкать от привычек сложно). Но в итоге я стал лучше, начал отстаивать все передовые практики. Меня слышали и уважали, потому что я добился успеха. Несколько лет спустя я выгорел, пытаясь изменить компанию, которая находилась в таком же состоянии отрицания, что и я сам несколько лет назад.
Мне не нужно переживать прошлое
Каждый из нас вспоминал времена, когда всё шло идеально. Спустя десять лет работы сеньором, я могу сказать, что я-«молодой сеньор», много знал о технологиях, но мало о людях и корпорациях. Я мог действовать самостоятельно, когда позволяли, но моё видение ограничивалось тем, что мне было позволено видеть. Я был способным и всесторонне развитым технически, но в бизнесе у меня был эффект Даннинга-Крюгера.
Что меня ждёт в будущем?
Лет 10 назад один из моих тимлидов углубился в управление персоналом, признав, что он «слишком стар, чтобы идти в ногу с новейшими технологиями и практиками». Другой менеджер, наоборот, сказал, что выбрал менеджмент, потому что разработка со временем стала скучной. Ему нужен был новый вызов.
Я всегда думал, что пойду по пути техлида. Но я оставил стек, на котором специализировался несколько лет. Сейчас я вряд ли могу продемонстрировать какие-либо лидерские качества в текущем стеке. DevOps выглядит привлекательно, поскольку соответствует тому, что я считаю важным. Хотя я бы скучал по временам, когда был и разработчиком функций, и тестировщиком, и DevOpsом.
Итого
У меня была полноценная карьера. Я не сияю так ярко, как раньше, но я стал мудрее. Молодым разработчикам есть на что опереться, чтобы они могли сиять. Никогда ещё технологии разработки ПО не были так многослойны и многообразны. Работа с современными языками программирования может доставлять удовольствие. Мы достаточно раз терпели неудачи, чтобы показать вам, что не работает, и у нас достаточно примеров того, что работает стабильно. Ваша главная задача сейчас — выделяться. Сияйте ярко!
PS: Напишите в комментариях, как изменились ваши приоритеты в карьере с течением времени.
Источник: https://levelup.gitconnected.com/im-a-middle-aged-developer-and-my-time-to-shine-has-sunset-a1b5d5c6ff2d
👍12👎1
День 2452. #ВопросыНаСобеседовании
Марк Прайс в своей книге предложил свой набор из 60 вопросов на собеседовании.
5. Свойства и индексаторы
«Можете ли вы объяснить разницу между свойствами и индексаторами в C# и привести примеры ситуаций, в которых каждый из них может быть использован?»
Хороший ответ
«В C# свойства и индексаторы используются для инкапсуляции данных, но они служат разным целям и используются в разных контекстах. Свойства действуют как комбинация метода и поля, предоставляя способ получения и установки значений с дополнительной логикой, используя синтаксис, подобный синтаксису полей. Свойства наиболее подходят, когда требуется предоставить данные класса с потенциальной проверкой, вычислением или преобразованием. Например, класс Person может иметь свойство DateOfBirth, которое гарантирует, что дата установлена в прошлом, и вычисляет возраст человека при получении.
Индексаторы позволяют индексировать объект как массив, хотя ключ может быть любого типа данных, а не только целочисленным. Это особый тип свойства, позволяющий получать доступ к классам с помощью оператора доступа к массиву []. Индексаторы особенно полезны, когда класс представляет собой коллекцию элементов. Например, класс Library может использовать индексатор, чтобы предоставить клиентам доступ к книгам по числовому индексу.
Как свойства, так и индексаторы включают методы доступа get и set (или только один из них), и оба могут включать в себя дополнительную логику в этих методах для обеспечения инкапсуляции или управления побочными эффектами.»
Часто встречающийся неточный ответ:
«Я использую свойства, когда мне нужно хранить данные в полях, и индексаторы, когда я хочу использовать массивы в своих классах».
Этот ответ отражает непонимание как свойств, так и индексаторов:
- Непонимание свойств: Свойства предназначены не только для хранения данных; они используются для инкапсуляции доступа к данным и могут включать логику проверки, значения по умолчанию или другие преобразования. Это не просто поля, а более сложные функции.
- Непонимание индексаторов: Индексаторы — это не просто способ реализации массивов внутри классов. Они позволяют индексировать экземпляр класса подобно массивам, но и служат для того, чтобы класс вёл себя как коллекция. Это непонимание принижает роль индексаторов в абстракции и инкапсуляции.
Ошибка обычно возникает из-за отсутствия глубокого понимания принципов объектно-ориентированного программирования и роли, которую эти структуры играют в обеспечении целостности данных и создании гибкой, поддерживаемой архитектуры кода.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс в своей книге предложил свой набор из 60 вопросов на собеседовании.
5. Свойства и индексаторы
«Можете ли вы объяснить разницу между свойствами и индексаторами в C# и привести примеры ситуаций, в которых каждый из них может быть использован?»
Хороший ответ
«В C# свойства и индексаторы используются для инкапсуляции данных, но они служат разным целям и используются в разных контекстах. Свойства действуют как комбинация метода и поля, предоставляя способ получения и установки значений с дополнительной логикой, используя синтаксис, подобный синтаксису полей. Свойства наиболее подходят, когда требуется предоставить данные класса с потенциальной проверкой, вычислением или преобразованием. Например, класс Person может иметь свойство DateOfBirth, которое гарантирует, что дата установлена в прошлом, и вычисляет возраст человека при получении.
Индексаторы позволяют индексировать объект как массив, хотя ключ может быть любого типа данных, а не только целочисленным. Это особый тип свойства, позволяющий получать доступ к классам с помощью оператора доступа к массиву []. Индексаторы особенно полезны, когда класс представляет собой коллекцию элементов. Например, класс Library может использовать индексатор, чтобы предоставить клиентам доступ к книгам по числовому индексу.
Как свойства, так и индексаторы включают методы доступа get и set (или только один из них), и оба могут включать в себя дополнительную логику в этих методах для обеспечения инкапсуляции или управления побочными эффектами.»
Часто встречающийся неточный ответ:
«Я использую свойства, когда мне нужно хранить данные в полях, и индексаторы, когда я хочу использовать массивы в своих классах».
Этот ответ отражает непонимание как свойств, так и индексаторов:
- Непонимание свойств: Свойства предназначены не только для хранения данных; они используются для инкапсуляции доступа к данным и могут включать логику проверки, значения по умолчанию или другие преобразования. Это не просто поля, а более сложные функции.
- Непонимание индексаторов: Индексаторы — это не просто способ реализации массивов внутри классов. Они позволяют индексировать экземпляр класса подобно массивам, но и служат для того, чтобы класс вёл себя как коллекция. Это непонимание принижает роль индексаторов в абстракции и инкапсуляции.
Ошибка обычно возникает из-за отсутствия глубокого понимания принципов объектно-ориентированного программирования и роли, которую эти структуры играют в обеспечении целостности данных и создании гибкой, поддерживаемой архитектуры кода.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍11
День 2453. #МоиИнструменты
RazorConsole
Если среди нас есть те, кто скучает по временам Norton Commander, терпеть не может мышь и кому «все эти ваши UI как кость в горле, дайте консоль», у меня для вас хорошие новости. NuGet-пакет RazorConsole стирает грань между разработкой современных веб-UI и консольными приложениями. Он позволяет создавать сложные интерфейсы в консоли с использованием компонентов Razor.
Стандартный пример в шаблоне приложения Blazor – компонент счётчика. Посмотрим, как это выглядит в RazorConsole.
Для начала создадим новый консольный проект. Добавим в него NuGet-пакет RazorConsole:
Кроме того, RazorConsole требуется SDK Microsoft.NET.Sdk.Razor для компиляции компонентов Razor. Поэтому нужно обновить файл проекта (.csproj) для его использования:
Добавим простой компонент Razor в файл
Мы разместили текст, элемент счётчика и 2 кнопки (увеличивающую и уменьшающую счётчик). Всё это мы поместили в простую таблицу, используя готовые компоненты
В файле
Пример работы показан на видео ниже. Активная кнопка выделяется голубым, перемещаться можно клавишей
Таким образом можно создавать UI в консоли, используя знакомые компоненты Razor с полной поддержкой привязки данных, обработки событий и методов жизненного цикла компонентов. Пакет содержит 15 готовых компонентов, охватывающих все необходимые функции:
- Разметка: Grid, Columns, Rows, Align, Padder;
- Поля ввода: TextInput, TextButton, Select;
- Отображение: Markup, Panel, Border, Figlet, SyntaxHighlighter, Table;
- Утилиты: Spinner, Newline.
Также имеется интерактивная галерея компонентов, которая поставляется как dotnet утилита RazorConsole.Gallery. Она содержит документацию по всем компонентам.
Источник: https://github.com/LittleLittleCloud/RazorConsole/
RazorConsole
Если среди нас есть те, кто скучает по временам Norton Commander, терпеть не может мышь и кому «все эти ваши UI как кость в горле, дайте консоль», у меня для вас хорошие новости. NuGet-пакет RazorConsole стирает грань между разработкой современных веб-UI и консольными приложениями. Он позволяет создавать сложные интерфейсы в консоли с использованием компонентов Razor.
Стандартный пример в шаблоне приложения Blazor – компонент счётчика. Посмотрим, как это выглядит в RazorConsole.
Для начала создадим новый консольный проект. Добавим в него NuGet-пакет RazorConsole:
dotnet add package RazorConsole.Core
Кроме того, RazorConsole требуется SDK Microsoft.NET.Sdk.Razor для компиляции компонентов Razor. Поэтому нужно обновить файл проекта (.csproj) для его использования:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<!-- … -->
</Project>
Добавим простой компонент Razor в файл
Counter.razor:@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Web
@using RazorConsole.Components
<Rows>
<Columns>
<p>Current count</p>
<Markup Content="@count.ToString()"
Foreground="@Spectre.Console.Color.Green" />
</Columns>
<Columns>
<TextButton Content="+1"
OnClick="Increment"
BackgroundColor="@Spectre.Console.Color.Grey"
FocusedColor="@Spectre.Console.Color.Blue" />
<TextButton Content="-1"
OnClick="Decrement"
BackgroundColor="@Spectre.Console.Color.Grey"
FocusedColor="@Spectre.Console.Color.Blue" />
</Columns>
</Rows>
@code {
private int count = 0;
private void Increment() => count++;
private void Decrement() => count--;
}
Мы разместили текст, элемент счётчика и 2 кнопки (увеличивающую и уменьшающую счётчик). Всё это мы поместили в простую таблицу, используя готовые компоненты
Rows и Columns (о них позже).В файле
Program.cs нам осталось добавить всего одну строку:await AppHost.RunAsync<Counter>();
Пример работы показан на видео ниже. Активная кнопка выделяется голубым, перемещаться можно клавишей
Tab, а нажимать на кнопку клавишей Enter.Таким образом можно создавать UI в консоли, используя знакомые компоненты Razor с полной поддержкой привязки данных, обработки событий и методов жизненного цикла компонентов. Пакет содержит 15 готовых компонентов, охватывающих все необходимые функции:
- Разметка: Grid, Columns, Rows, Align, Padder;
- Поля ввода: TextInput, TextButton, Select;
- Отображение: Markup, Panel, Border, Figlet, SyntaxHighlighter, Table;
- Утилиты: Spinner, Newline.
Также имеется интерактивная галерея компонентов, которая поставляется как dotnet утилита RazorConsole.Gallery. Она содержит документацию по всем компонентам.
Источник: https://github.com/LittleLittleCloud/RazorConsole/
This media is not supported in your browser
VIEW IN TELEGRAM
👍12
День 2454. #ЧтоНовенького
Вышел .NET 10 Release Candidate 2
Microsoft выпустили .NET 10 Release Candidate 2, финальную предварительную сборку перед релизом. Как сообщает команда .NET, RC 2 поставляется с лицензией на поддержку go-live, что позволяет разворачивать продуктовую версию и одновременно проверять платформу перед её официальным релизом. Сборка поддерживается в Visual Studio 2026 Insiders и Visual Studio Code с помощью C# Dev Kit.
Официальная дата выпуска .NET 10 — 11 ноября 2025 года. Это будет релиз с долгосрочной поддержкой (LTS), обеспечивающий три года исправлений и обновлений. Release Candidate 1 (RC1) был доступен 9 сентября, а RC2 — 14 октября. В Microsoft заявили, что этот релиз в первую очередь ориентирован на валидацию, качество и стабильность, а не на добавление новых функций. Команда сделала акцент на постепенном улучшении качества, чтобы обеспечить плавный переход к GA и совместимость со всеми поддерживаемыми рабочими нагрузками.
1. MAUI
Windows теперь поддерживает разрешения на доступ к микрофону через Permissions.RequestAsync<Permissions.Microphone>(), обеспечивая единую модель разрешений для всех платформ. Android получает поддержку SafeAreaEdges, что улучшает поведение макета при отрисовке от края до края и наложениях клавиатуры.
Также улучшили генерацию исходного кода XAML, предлагающую более быструю отладку генерации представлений и упрощённый механизм настройки через свойство <MauiXamlInflator>SourceGen</MauiXamlInflator>. В Microsoft описали эти обновления как часть продолжающейся работы по повышению производительности и предсказуемости разработки MAUI.
Для Android, в RC 2 представлены привязки API 36.1, разработанные совместно с командой платформы Uno. Проекты могут быть ориентированы на net10.0-android36.1 для доступа к новейшим API платформы, при этом EnablePreviewFeatures по-прежнему временно требуется. В этом выпуске также продолжается экспериментальное внедрение CoreCLR для Android, позволяя разработчикам отключать Mono (UseMonoRuntime=false) и запускать приложения в новой среде выполнения. Хотя эта функция пока не готова к использованию в промышленной среде, по заявлению Microsoft, она представляет собой важный шаг к унификации среды выполнения на разных платформах.
Для разработчиков Apple теперь доступны привязки Xcode 26 для .NET для iOS, macOS, Mac Catalyst и tvOS, что обеспечивает совместимость с новейшими SDK Apple и единообразие между целевыми платформами .NET 9 и .NET 10.
2. Entity Framework Core
Добавлены обновления стабильности и надёжности, такие как улучшенная обработка сложных сопоставлений JSON, уточнённые границы транзакций миграции, поддержка повторных запросов через ExecutionStrategy и новые предупреждения анализатора о небезопасной конкатенации SQL.
3. SDK
Добавлена возможность запускать задачи MSBuild на базе dotnet в Visual Studio и msbuild.exe, устраняя давний разрыв между средами сборки dotnet и .NET Framework. Объявляя задачи с Runtime="NET" и TaskFactory="TaskHostFactory", авторы могут повторно использовать одну и ту же реализацию в CLI и IDE без необходимости настройки на несколько платформ.
Как пояснила команда разработчиков, эта функция знаменует собой первый шаг в более масштабной модернизации MSBuild. В будущих выпусках планируется добавить дополнительные возможности в MSBuild, чтобы упростить написание и использование задач .NET, включая:
- Автоматическое обнаружение и загрузку задач .NET без необходимости указания метаданных среды выполнения или TaskFactory;
- Снижение нагрузки на производительность IPC между движком MSBuild и задачами при выполнении вне процесса;
- Поддержку функции Host Object для задач .NET, выполняемых вне процесса.
.NET 10 RC 2 предназначена для проверки качества релиза, что открывает путь к полноценному релизу в следующем месяце. Разработчикам рекомендуется протестировать приложения с RC 2 и поделиться отзывами в официальном обсуждении на GitHub до релиза .NET 10 — 11 ноября 2025 года.
Источник: https://www.infoq.com/news/2025/10/dotnet-10-rc-2-release/
Вышел .NET 10 Release Candidate 2
Microsoft выпустили .NET 10 Release Candidate 2, финальную предварительную сборку перед релизом. Как сообщает команда .NET, RC 2 поставляется с лицензией на поддержку go-live, что позволяет разворачивать продуктовую версию и одновременно проверять платформу перед её официальным релизом. Сборка поддерживается в Visual Studio 2026 Insiders и Visual Studio Code с помощью C# Dev Kit.
Официальная дата выпуска .NET 10 — 11 ноября 2025 года. Это будет релиз с долгосрочной поддержкой (LTS), обеспечивающий три года исправлений и обновлений. Release Candidate 1 (RC1) был доступен 9 сентября, а RC2 — 14 октября. В Microsoft заявили, что этот релиз в первую очередь ориентирован на валидацию, качество и стабильность, а не на добавление новых функций. Команда сделала акцент на постепенном улучшении качества, чтобы обеспечить плавный переход к GA и совместимость со всеми поддерживаемыми рабочими нагрузками.
1. MAUI
Windows теперь поддерживает разрешения на доступ к микрофону через Permissions.RequestAsync<Permissions.Microphone>(), обеспечивая единую модель разрешений для всех платформ. Android получает поддержку SafeAreaEdges, что улучшает поведение макета при отрисовке от края до края и наложениях клавиатуры.
Также улучшили генерацию исходного кода XAML, предлагающую более быструю отладку генерации представлений и упрощённый механизм настройки через свойство <MauiXamlInflator>SourceGen</MauiXamlInflator>. В Microsoft описали эти обновления как часть продолжающейся работы по повышению производительности и предсказуемости разработки MAUI.
Для Android, в RC 2 представлены привязки API 36.1, разработанные совместно с командой платформы Uno. Проекты могут быть ориентированы на net10.0-android36.1 для доступа к новейшим API платформы, при этом EnablePreviewFeatures по-прежнему временно требуется. В этом выпуске также продолжается экспериментальное внедрение CoreCLR для Android, позволяя разработчикам отключать Mono (UseMonoRuntime=false) и запускать приложения в новой среде выполнения. Хотя эта функция пока не готова к использованию в промышленной среде, по заявлению Microsoft, она представляет собой важный шаг к унификации среды выполнения на разных платформах.
Для разработчиков Apple теперь доступны привязки Xcode 26 для .NET для iOS, macOS, Mac Catalyst и tvOS, что обеспечивает совместимость с новейшими SDK Apple и единообразие между целевыми платформами .NET 9 и .NET 10.
2. Entity Framework Core
Добавлены обновления стабильности и надёжности, такие как улучшенная обработка сложных сопоставлений JSON, уточнённые границы транзакций миграции, поддержка повторных запросов через ExecutionStrategy и новые предупреждения анализатора о небезопасной конкатенации SQL.
3. SDK
Добавлена возможность запускать задачи MSBuild на базе dotnet в Visual Studio и msbuild.exe, устраняя давний разрыв между средами сборки dotnet и .NET Framework. Объявляя задачи с Runtime="NET" и TaskFactory="TaskHostFactory", авторы могут повторно использовать одну и ту же реализацию в CLI и IDE без необходимости настройки на несколько платформ.
Как пояснила команда разработчиков, эта функция знаменует собой первый шаг в более масштабной модернизации MSBuild. В будущих выпусках планируется добавить дополнительные возможности в MSBuild, чтобы упростить написание и использование задач .NET, включая:
- Автоматическое обнаружение и загрузку задач .NET без необходимости указания метаданных среды выполнения или TaskFactory;
- Снижение нагрузки на производительность IPC между движком MSBuild и задачами при выполнении вне процесса;
- Поддержку функции Host Object для задач .NET, выполняемых вне процесса.
.NET 10 RC 2 предназначена для проверки качества релиза, что открывает путь к полноценному релизу в следующем месяце. Разработчикам рекомендуется протестировать приложения с RC 2 и поделиться отзывами в официальном обсуждении на GitHub до релиза .NET 10 — 11 ноября 2025 года.
Источник: https://www.infoq.com/news/2025/10/dotnet-10-rc-2-release/
👍2
День 2455. #ЗаметкиНаПолях
Когда Type.FullName Возвращает null
Немного бесполезной информации вам в ленту. Казалось бы, имя типа в .NET всегда должно быть известно. Однако сигнатура метода Type.FullName такая:
Такое поведение может показаться неожиданным, но существуют определённые сценарии, в которых среда выполнения .NET не может сгенерировать корректное полное имя для типа. Вот два основных случая, когда Type.FullName возвращает null.
1. Обобщённые типы с открытыми параметрами типа
При создании обобщённого типа, содержащего несвязанные обобщённые параметры:
2. Указатели на функции
Указатели на функции, введённые в C#9, также имеют null в FullName:
Источник: https://www.meziantou.net/understanding-when-type-fullname-returns-null-in-dotnet.htm
Когда Type.FullName Возвращает null
Немного бесполезной информации вам в ленту. Казалось бы, имя типа в .NET всегда должно быть известно. Однако сигнатура метода Type.FullName такая:
public abstract string? FullName { get; }Такое поведение может показаться неожиданным, но существуют определённые сценарии, в которых среда выполнения .NET не может сгенерировать корректное полное имя для типа. Вот два основных случая, когда Type.FullName возвращает null.
1. Обобщённые типы с открытыми параметрами типа
При создании обобщённого типа, содержащего несвязанные обобщённые параметры:
var list = typeof(IList<>);
var dict = typeof(IDictionary<,>);
var listOfDictionaries = list.MakeGenericType(dict);
// IList<IDictionary<,>>
Assert.Null(listOfDictionaries.FullName);
2. Указатели на функции
Указатели на функции, введённые в C#9, также имеют null в FullName:
var functionPointerType = typeof(delegate*<int, void>);
Assert.Null(functionPointerType.FullName);
Источник: https://www.meziantou.net/understanding-when-type-fullname-returns-null-in-dotnet.htm
👍14
День 2456. #TipsAndTricks
6 Шагов для Правильной Настройки Нового .NET-проекта. Начало
Начинать новый .NET-проект всегда волнительно. Но легко пропустить подготовительную работу, которая делает проект масштабируемым и поддерживаемым. Вот несколько ключевых шагов, которые значительно облегчат вам (и вашим коллегам) жизнь в дальнейшем.
1. Единый стиль кода
Файл .editorconfig гарантирует, что все участники команды будут использовать одинаковые соглашения по форматированию и именованию, что позволяет избежать несоответствий в отступах и случайных правил именования.
Можно создать его прямо в Visual Studio. Щелкните правой кнопкой на решении Add -> New Editorconfig (Добавить -> Новый Editorconfig). Конфигурация по умолчанию — отличное начало. Но вы можете настроить её дополнительно в соответствии с предпочтениями команды. Разместите файл в корне решения, чтобы все проекты следовали одним и тем же правилам. При необходимости можно переопределить определённые настройки во вложенных папках, поместив туда свой файл .editorconfig. Вот пара примеров:
- из репозитория среды исполнения .NET
- от Милана общий для проектов .NET
2. Централизованная конфигурации сборки
Файл Directory.Build.props позволяет определить параметры сборки, применяемые к каждому проекту в решении:
Это позволяет сохранить чистоту и единообразие ваших файлов .csproj, поскольку нет необходимости повторять эти свойства в каждом проекте. Если позже вы захотите включить статические анализаторы или настроить параметры сборки, вы можете сделать это один раз здесь. Преимущество в том, что файлы .csproj становятся практически пустыми, большую часть времени содержащими только ссылки на NuGet-пакеты.
3. Централизованное управление пакетами
По мере роста решения управление версиями NuGet-пакетов в нескольких проектах становится проблематичным. Именно здесь на помощь приходит централизованное управление пакетами. Создайте файл с именем Directory.Packages.props в корне:
Теперь, когда нужно сослаться на NuGet-пакет в проекте, не нужно указывать версию. Можно использовать только имя пакета:
Всё управление версиями осуществляется централизованно. Это упрощает обновление зависимостей и позволяет избежать дрейфа версий между проектами. При необходимости вы по-прежнему можете переопределять версии в отдельных проектах.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/6-steps-for-setting-up-a-new-dotnet-project-the-right-way
6 Шагов для Правильной Настройки Нового .NET-проекта. Начало
Начинать новый .NET-проект всегда волнительно. Но легко пропустить подготовительную работу, которая делает проект масштабируемым и поддерживаемым. Вот несколько ключевых шагов, которые значительно облегчат вам (и вашим коллегам) жизнь в дальнейшем.
1. Единый стиль кода
Файл .editorconfig гарантирует, что все участники команды будут использовать одинаковые соглашения по форматированию и именованию, что позволяет избежать несоответствий в отступах и случайных правил именования.
Можно создать его прямо в Visual Studio. Щелкните правой кнопкой на решении Add -> New Editorconfig (Добавить -> Новый Editorconfig). Конфигурация по умолчанию — отличное начало. Но вы можете настроить её дополнительно в соответствии с предпочтениями команды. Разместите файл в корне решения, чтобы все проекты следовали одним и тем же правилам. При необходимости можно переопределить определённые настройки во вложенных папках, поместив туда свой файл .editorconfig. Вот пара примеров:
- из репозитория среды исполнения .NET
- от Милана общий для проектов .NET
2. Централизованная конфигурации сборки
Файл Directory.Build.props позволяет определить параметры сборки, применяемые к каждому проекту в решении:
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>
Это позволяет сохранить чистоту и единообразие ваших файлов .csproj, поскольку нет необходимости повторять эти свойства в каждом проекте. Если позже вы захотите включить статические анализаторы или настроить параметры сборки, вы можете сделать это один раз здесь. Преимущество в том, что файлы .csproj становятся практически пустыми, большую часть времени содержащими только ссылки на NuGet-пакеты.
3. Централизованное управление пакетами
По мере роста решения управление версиями NuGet-пакетов в нескольких проектах становится проблематичным. Именно здесь на помощь приходит централизованное управление пакетами. Создайте файл с именем Directory.Packages.props в корне:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.15.0.120848" />
</ItemGroup>
</Project>
Теперь, когда нужно сослаться на NuGet-пакет в проекте, не нужно указывать версию. Можно использовать только имя пакета:
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
Всё управление версиями осуществляется централизованно. Это упрощает обновление зависимостей и позволяет избежать дрейфа версий между проектами. При необходимости вы по-прежнему можете переопределять версии в отдельных проектах.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/6-steps-for-setting-up-a-new-dotnet-project-the-right-way
1👍38
День 2457. #TipsAndTricks
6 Шагов для Правильной Настройки Нового .NET-проекта. Окончание
Начало
4. Статический анализ кода
Помогает выявлять потенциальные ошибки и поддерживать качество кода. В .NET есть набор встроенных анализаторов, но есть отличный NuGet-пакет SonarAnalyzer.CSharp для более полной проверки.
Также его можно добавить как глобальную ссылку в Directory.Build.props:
Это в сочетании с такими настройками:
…и ваши сборки будут завершаться неудачей при серьёзных недостатках качества кода. Это может быть отличной подстраховкой. Но поначалу это может мешать. Если некоторые правила не соответствуют вашему контексту, вы можете изменить или отключить их в файле .editorconfig, установив для важности правила значение none.
5. Настройка локальной оркестровки
Для обеспечения согласованности локальной среды в команде вам понадобится оркестровка контейнеров. Есть два основных варианта.
1) Docker Compose
Добавьте поддержку Docker Compose в Visual Studio. Будет добавлен файл docker-compose.yml, в котором вы можете определить сервисы:
Это позволит каждому разработчику локально развернуть один и тот же стек при помощи одной команды.
2) .NET Aspire
.NET Aspire выводит оркестровку на новый уровень. Он обеспечивает обнаружение сервисов, телеметрию и оптимизированную настройку, интегрированные с вашими проектами .NET. Вы можете добавить проект .NET и ресурс Postgres всего несколькими строками кода:
Aspire также использует Docker, но предоставляет более широкие возможности для разработки.
Не важно, Docker Compose или Aspire, цель одна: воспроизводимая, надёжная локальная конфигурация, которая работает одинаково на всех машинах.
6. Автоматизация сборки
Простой рабочий процесс GitHub Actions для проверки каждого коммита .github/workflows/build.yml:
Это гарантирует, что проект всегда будет собираться и проходить тесты, а проблемы будут выявляться до того, как они попадут в продакшн. Если сборка непрерывной интеграции (CI) завершится неудачей, вы сразу поймете, что что-то не так.
Что касается тестирования, изучите:
- Тестирование архитектуры,
- Интеграционное тестирование с Testcontainers.
Это даст уверенность в том, что код работает как ожидалось в среде, максимально приближенной к производственной.
Источник: https://www.milanjovanovic.tech/blog/6-steps-for-setting-up-a-new-dotnet-project-the-right-way
6 Шагов для Правильной Настройки Нового .NET-проекта. Окончание
Начало
4. Статический анализ кода
Помогает выявлять потенциальные ошибки и поддерживать качество кода. В .NET есть набор встроенных анализаторов, но есть отличный NuGet-пакет SonarAnalyzer.CSharp для более полной проверки.
Install-Package SonarAnalyzer.CSharp
Также его можно добавить как глобальную ссылку в Directory.Build.props:
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" />
</ItemGroup>
Это в сочетании с такими настройками:
<Project>
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>All</AnalysisMode>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
</Project>
…и ваши сборки будут завершаться неудачей при серьёзных недостатках качества кода. Это может быть отличной подстраховкой. Но поначалу это может мешать. Если некоторые правила не соответствуют вашему контексту, вы можете изменить или отключить их в файле .editorconfig, установив для важности правила значение none.
5. Настройка локальной оркестровки
Для обеспечения согласованности локальной среды в команде вам понадобится оркестровка контейнеров. Есть два основных варианта.
1) Docker Compose
Добавьте поддержку Docker Compose в Visual Studio. Будет добавлен файл docker-compose.yml, в котором вы можете определить сервисы:
services:
webapi:
build: .
postgres:
image: postgres:18
environment:
POSTGRES_PASSWORD: password
Это позволит каждому разработчику локально развернуть один и тот же стек при помощи одной команды.
2) .NET Aspire
.NET Aspire выводит оркестровку на новый уровень. Он обеспечивает обнаружение сервисов, телеметрию и оптимизированную настройку, интегрированные с вашими проектами .NET. Вы можете добавить проект .NET и ресурс Postgres всего несколькими строками кода:
var postgres = builder.AddPostgres("demo-db");
builder.AddProject<WebApi>("webapi")
.WithReference(postgres)
.WaitFor(postgres);
builder.Build().Run();Aspire также использует Docker, но предоставляет более широкие возможности для разработки.
Не важно, Docker Compose или Aspire, цель одна: воспроизводимая, надёжная локальная конфигурация, которая работает одинаково на всех машинах.
6. Автоматизация сборки
Простой рабочий процесс GitHub Actions для проверки каждого коммита .github/workflows/build.yml:
name: Build
on:
push:
# Выполнение только на ветке main
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- run: dotnet restore
- run: dotnet build --no-restore --configuration Release
- run: dotnet test --no-build --configuration Release
Это гарантирует, что проект всегда будет собираться и проходить тесты, а проблемы будут выявляться до того, как они попадут в продакшн. Если сборка непрерывной интеграции (CI) завершится неудачей, вы сразу поймете, что что-то не так.
Что касается тестирования, изучите:
- Тестирование архитектуры,
- Интеграционное тестирование с Testcontainers.
Это даст уверенность в том, что код работает как ожидалось в среде, максимально приближенной к производственной.
Источник: https://www.milanjovanovic.tech/blog/6-steps-for-setting-up-a-new-dotnet-project-the-right-way
👍18
День 2458. #ЧтоНовенького
Microsoft Исправила Самую Серьёзную Уязвимость в ASP.NET Core
На прошлой неделе Microsoft исправили уязвимость, получившую «самый высокий» уровень серьёзности из-за уязвимости безопасности ASP.NET Core.
Эта ошибка подмены HTTP-запросов (CVE-2025-55315) была обнаружена в веб-сервере Kestrel ASP.NET Core. Она позволяет аутентифицированным злоумышленникам подделывать другой HTTP-запрос для кражи учётных данных других пользователей или обхода средств безопасности на стороне клиента.
«Злоумышленник, успешно воспользовавшийся этой уязвимостью, может просматривать конфиденциальную информацию, такую как учётные данные других пользователей (Конфиденциальность), и вносить изменения в содержимое файлов на целевом сервере (Целостность), а также может вызвать сбой на сервере (Доступность)», — заявили в Microsoft во вторник в информационном бюллетене.
Для устранения этой уязвимости Microsoft выпустили обновления безопасности для Microsoft Visual Studio 2022, ASP.NET Core 2.3, ASP.NET Core 8.0 и ASP.NET Core 9.0, а также для пакета Microsoft.AspNetCore.Server.Kestrel.Core для приложений ASP.NET Core 2.x.
Чтобы защитить свои приложения ASP.NET Core от потенциальных атак, Microsoft рекомендует разработчикам и пользователям принять следующие меры:
- Если вы используете .NET 8 или более позднюю версию, установите обновление .NET из Центра обновления Microsoft, затем перезапустите приложение или перезагрузите компьютер.
- Если вы используете .NET 2.3, обновите ссылку на пакет Microsoft.AspNet.Server.Kestrel.Core до версии 2.3.6, затем перекомпилируйте и повторно разверните приложение.
- Если вы используете автономное/однофайловое приложение, установите обновление .NET, перекомпилируйте и повторно разверните.
Как пояснил руководитель технической программы безопасности .NET Барри Дорранс, последствия атак CVE-2025-55315 будут зависеть от целевого приложения ASP.NET, и успешная эксплуатация уязвимости может позволить злоумышленникам войти в систему под другим пользователем (для повышения привилегий), выполнить внутренний запрос (при атаках с подделкой запросов на стороне сервера), обойти проверки на подделку межсайтовых запросов (CSRF) или выполнить атаки с использованием инъекций.
«Мы не знаем, что из этого возможно, потому что всё зависит от того, как вы написали своё приложение. Поэтому мы оцениваем уровень риска, имея в виду наихудший возможный случай — обход функции безопасности, который позволяет изменить привилегии, — сказал Дорранс. — Вероятно ли это? Скорее всего, нет, если только код вашего приложения не делает что-то странное и не пропускает ряд проверок, которые он должен выполнять при каждом запросе. Тем не менее, пожалуйста, обновитесь».
Источник: https://www.bleepingcomputer.com/news/microsoft/microsoft-fixes-highest-severity-aspnet-core-flaw-ever/
Microsoft Исправила Самую Серьёзную Уязвимость в ASP.NET Core
На прошлой неделе Microsoft исправили уязвимость, получившую «самый высокий» уровень серьёзности из-за уязвимости безопасности ASP.NET Core.
Эта ошибка подмены HTTP-запросов (CVE-2025-55315) была обнаружена в веб-сервере Kestrel ASP.NET Core. Она позволяет аутентифицированным злоумышленникам подделывать другой HTTP-запрос для кражи учётных данных других пользователей или обхода средств безопасности на стороне клиента.
«Злоумышленник, успешно воспользовавшийся этой уязвимостью, может просматривать конфиденциальную информацию, такую как учётные данные других пользователей (Конфиденциальность), и вносить изменения в содержимое файлов на целевом сервере (Целостность), а также может вызвать сбой на сервере (Доступность)», — заявили в Microsoft во вторник в информационном бюллетене.
Для устранения этой уязвимости Microsoft выпустили обновления безопасности для Microsoft Visual Studio 2022, ASP.NET Core 2.3, ASP.NET Core 8.0 и ASP.NET Core 9.0, а также для пакета Microsoft.AspNetCore.Server.Kestrel.Core для приложений ASP.NET Core 2.x.
Чтобы защитить свои приложения ASP.NET Core от потенциальных атак, Microsoft рекомендует разработчикам и пользователям принять следующие меры:
- Если вы используете .NET 8 или более позднюю версию, установите обновление .NET из Центра обновления Microsoft, затем перезапустите приложение или перезагрузите компьютер.
- Если вы используете .NET 2.3, обновите ссылку на пакет Microsoft.AspNet.Server.Kestrel.Core до версии 2.3.6, затем перекомпилируйте и повторно разверните приложение.
- Если вы используете автономное/однофайловое приложение, установите обновление .NET, перекомпилируйте и повторно разверните.
Как пояснил руководитель технической программы безопасности .NET Барри Дорранс, последствия атак CVE-2025-55315 будут зависеть от целевого приложения ASP.NET, и успешная эксплуатация уязвимости может позволить злоумышленникам войти в систему под другим пользователем (для повышения привилегий), выполнить внутренний запрос (при атаках с подделкой запросов на стороне сервера), обойти проверки на подделку межсайтовых запросов (CSRF) или выполнить атаки с использованием инъекций.
«Мы не знаем, что из этого возможно, потому что всё зависит от того, как вы написали своё приложение. Поэтому мы оцениваем уровень риска, имея в виду наихудший возможный случай — обход функции безопасности, который позволяет изменить привилегии, — сказал Дорранс. — Вероятно ли это? Скорее всего, нет, если только код вашего приложения не делает что-то странное и не пропускает ряд проверок, которые он должен выполнять при каждом запросе. Тем не менее, пожалуйста, обновитесь».
Источник: https://www.bleepingcomputer.com/news/microsoft/microsoft-fixes-highest-severity-aspnet-core-flaw-ever/
👍15
День 2459. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы). Я решил разобрать их тут. Начнём с 4го, поскольку первые 3 приведены в его книге, обзор на которую я недавно выкладывал.
6. Обобщения (дженерики)
«Можете объяснить преимущества использования обобщений в приложениях .NET и привести пример сценария, в котором использование обобщений может значительно улучшить качество и производительность кода?»
Хороший ответ
«Обобщения в .NET предоставляют возможность записывать определения классов, методов, делегатов или интерфейсов с параметром для типа, с которым они работают. Это обеспечивает повторное использование кода и типобезопасность без накладных расходов на упаковку или приведение типов, что часто встречается в необобщенных типах.
Основные преимущества использования обобщений включают в себя:
- Безопасность типов: обобщения позволяют указывать точный тип при создании экземпляра класса или метода, что снижает количество ошибок во время выполнения.
- Повторное использование кода: благодаря использованию параметров типа, обобщённые классы и методы могут работать с любым заданным типом, что позволяет разработчикам писать более гибкий и повторно используемый код.
- Повышение производительности: обобщения устраняют необходимость в упаковке и распаковке при работе с типами значений, что снижает потребление памяти и повышает производительность.
Пример сценария, в котором обобщения значительно повышают качество и производительность кода, — реализация классов-коллекций. Например, без обобщений список из целых чисел, хранил бы их как объекты (тип object), что потребовало бы упаковки. С обобщениями можно создать List<int>, в котором целые числа хранятся как целые числа, а не объекты, что устраняет необходимость в упаковке и распаковке, повышает производительность выполнения и снижает накладные расходы на память.
Подводя итог, можно сказать, что обобщения расширяют функциональность приложений .NET, делая их более эффективными, типобезопасными и гибкими.»
Часто встречающийся неверный ответ
«Я использую обобщения, когда мне нужно обрабатывать разные типы данных одним и тем же методом или когда я хочу, чтобы мой метод был гибким. Это всё равно, что заставить метод работать с любым типом данных».
Этот ответ демонстрирует понимание обобщений на элементарном уровне, но упускает важные детали и преимущества:
- Недостаток конкретики: В ответе расплывчато упоминается гибкость при работе с различными типами данных, но не говорится о важности типобезопасности и преимуществ производительности, обеспечиваемых обобщениями.
- Чрезмерное упрощение: Концепция обобщений сводится просто к «работе с любым типом», что упускает из виду истинное их предназначение — обеспечение повторного использования кода и безопасности в типоспецифичных операциях.
- Непонимание реализации: В этом ответе не проводится различие между использованием обобщений для обеспечения типобезопасности и необобщённым подходом с использованием типов object, что может привести к проблемам с производительностью и не обеспечивает проверку типов во время компиляции, которую обеспечивают обобщения.
Ошибка обычно возникает из-за поверхностного понимания обобщений, когда разработчик знает, что их можно использовать для работы с несколькими типами данных, но не до конца понимает или оценивает основные принципы и преимущества.
См. также Ковариантность и Контравариантность в Обобщениях.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы). Я решил разобрать их тут. Начнём с 4го, поскольку первые 3 приведены в его книге, обзор на которую я недавно выкладывал.
6. Обобщения (дженерики)
«Можете объяснить преимущества использования обобщений в приложениях .NET и привести пример сценария, в котором использование обобщений может значительно улучшить качество и производительность кода?»
Хороший ответ
«Обобщения в .NET предоставляют возможность записывать определения классов, методов, делегатов или интерфейсов с параметром для типа, с которым они работают. Это обеспечивает повторное использование кода и типобезопасность без накладных расходов на упаковку или приведение типов, что часто встречается в необобщенных типах.
Основные преимущества использования обобщений включают в себя:
- Безопасность типов: обобщения позволяют указывать точный тип при создании экземпляра класса или метода, что снижает количество ошибок во время выполнения.
- Повторное использование кода: благодаря использованию параметров типа, обобщённые классы и методы могут работать с любым заданным типом, что позволяет разработчикам писать более гибкий и повторно используемый код.
- Повышение производительности: обобщения устраняют необходимость в упаковке и распаковке при работе с типами значений, что снижает потребление памяти и повышает производительность.
Пример сценария, в котором обобщения значительно повышают качество и производительность кода, — реализация классов-коллекций. Например, без обобщений список из целых чисел, хранил бы их как объекты (тип object), что потребовало бы упаковки. С обобщениями можно создать List<int>, в котором целые числа хранятся как целые числа, а не объекты, что устраняет необходимость в упаковке и распаковке, повышает производительность выполнения и снижает накладные расходы на память.
Подводя итог, можно сказать, что обобщения расширяют функциональность приложений .NET, делая их более эффективными, типобезопасными и гибкими.»
Часто встречающийся неверный ответ
«Я использую обобщения, когда мне нужно обрабатывать разные типы данных одним и тем же методом или когда я хочу, чтобы мой метод был гибким. Это всё равно, что заставить метод работать с любым типом данных».
Этот ответ демонстрирует понимание обобщений на элементарном уровне, но упускает важные детали и преимущества:
- Недостаток конкретики: В ответе расплывчато упоминается гибкость при работе с различными типами данных, но не говорится о важности типобезопасности и преимуществ производительности, обеспечиваемых обобщениями.
- Чрезмерное упрощение: Концепция обобщений сводится просто к «работе с любым типом», что упускает из виду истинное их предназначение — обеспечение повторного использования кода и безопасности в типоспецифичных операциях.
- Непонимание реализации: В этом ответе не проводится различие между использованием обобщений для обеспечения типобезопасности и необобщённым подходом с использованием типов object, что может привести к проблемам с производительностью и не обеспечивает проверку типов во время компиляции, которую обеспечивают обобщения.
Ошибка обычно возникает из-за поверхностного понимания обобщений, когда разработчик знает, что их можно использовать для работы с несколькими типами данных, но не до конца понимает или оценивает основные принципы и преимущества.
См. также Ковариантность и Контравариантность в Обобщениях.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍10
День 2460. #ЗаметкиНаПолях
Встраивание и Структуры в C#
Сегодня рассмотрим встраивание структур в C#. И как оно может оптимизировать производительность несколькими интересными способами.
Встраивание
Встраивание — это оптимизация компилятора, которая заменяет вызов метода его телом. Например:
Компилятор может оптимизировать его до:
Очевидное преимущество здесь в том, что мы избегаем накладных расходов на вызов метода, но это также может увеличить размер кода и негативно сказаться на производительности (поскольку мы копируем тело метода во все места его вызова). Существует атрибут
Структуры
Неотъемлемой частью структур является то, что они, как правило, передаются по значению. Это означает, что при передаче структуры методу создаётся её копия. Т.е.:
В идеале структуры лучше сохранять неизменяемыми именно по этой причине. А также делать небольшими, чтобы избежать накладных расходов на копирование. И вот в чём «прелесть»: встраивая функцию, мы «стираем» необходимость копирования структуры в новый стековый фрейм. Т.е. встраивание может фактически удешевить передачу структур.
Посмотрите вот этот пример на sharplab.io. Вам не нужно понимать JIT-код ASM. Но сама разница в объёме кода между
PS: на самом деле JIT совершает множество гораздо более хитрых оптимизаций вашего кода. На последнем DotNext об этом был хороший доклад Дмитрия Егорова "JIT не волшебство: как он работает и как не мешать". У кого есть доступ, обязательно посмотрите. Остальные - подождите выхода на Youtube.
Источник: https://steven-giesel.com/blogPost/e89d7156-f3fd-4152-b78a-cb908bc43226/inlining-and-structs-in-c
Встраивание и Структуры в C#
Сегодня рассмотрим встраивание структур в C#. И как оно может оптимизировать производительность несколькими интересными способами.
Встраивание
Встраивание — это оптимизация компилятора, которая заменяет вызов метода его телом. Например:
public int Add(int a, int b) => a + b;
public int CalculateSum(int x, int y)
=> Add(x, y);
Компилятор может оптимизировать его до:
public int CalculateSum(int x, int y)
=> x + y;
Очевидное преимущество здесь в том, что мы избегаем накладных расходов на вызов метода, но это также может увеличить размер кода и негативно сказаться на производительности (поскольку мы копируем тело метода во все места его вызова). Существует атрибут
[MethodImpl(MethodImplOptions.AggressiveInlining)], который можно использовать, чтобы подсказать компилятору, что метод следует встраивать, даже если по умолчанию он этого не делает. Это всего лишь подсказка, и JIT всё равно может её проигнорировать. Мы также можем использовать [MethodImpl(MethodImplOptions.NoInlining)], чтобы предотвратить встраивание метода (подсказать JIT, что встраивать его не следует).Структуры
Неотъемлемой частью структур является то, что они, как правило, передаются по значению. Это означает, что при передаче структуры методу создаётся её копия. Т.е.:
public struct Point
{
public int X;
public int Y;
}
public void MovePoint(Point p)
{
p.X += 10;
p.Y += 10;
}
Point myPoint = new Point { X = 0, Y = 0 };
MovePoint(myPoint);
// myPoint всё ещё { X = 0, Y = 0 }
В идеале структуры лучше сохранять неизменяемыми именно по этой причине. А также делать небольшими, чтобы избежать накладных расходов на копирование. И вот в чём «прелесть»: встраивая функцию, мы «стираем» необходимость копирования структуры в новый стековый фрейм. Т.е. встраивание может фактически удешевить передачу структур.
Посмотрите вот этот пример на sharplab.io. Вам не нужно понимать JIT-код ASM. Но сама разница в объёме кода между
InlineVsNonInlineBenchmark.NonInline() и InlineVsNonInlineBenchmark.Inline() показывает, что Inline скорее всего будет работать быстрее. По сути, NonInline приходится много копировать (инструкции vmovdqu и vmovq), в то время как Inline просто считывает свойство, добавляет что-то и возвращает результат.PS: на самом деле JIT совершает множество гораздо более хитрых оптимизаций вашего кода. На последнем DotNext об этом был хороший доклад Дмитрия Егорова "JIT не волшебство: как он работает и как не мешать". У кого есть доступ, обязательно посмотрите. Остальные - подождите выхода на Youtube.
Источник: https://steven-giesel.com/blogPost/e89d7156-f3fd-4152-b78a-cb908bc43226/inlining-and-structs-in-c
👍8
День 2461. #ЧтоНовенького
Спонсорство на NuGet.org
Свершилось то, о чём так долго говорили большевики. Похоже, реагируя на волну коммерциализации популярных бесплатных NuGet-пакетов, NuGet.org предложили реализовать спонсорство, которое упрощает для пользователей возможность поддерживать авторов своих любимых пакетов.
NuGet.org теперь позволяет авторам пакетов добавлять URL спонсорства. Эта ссылка отображается в виде значка ❤️ или кнопки Sponsor this package (Спонсировать этот пакет) на странице пакета, направляя пользователей к безопасным и популярным платформам.
Пользователи пакетов теперь смогут поддерживать любимые пакеты. Найдите значок
Для владельцев пакетов
Чтобы установить спонсорство для пакета:
1. вы должны быть владельцем или совладельцем пакета на NuGet.org;
2. спонсорская ссылка должна быть на одну из одобренных платформ:
- GitHub Sponsors
- Patreon
- Open Collective
- Ko-fi
- Tidelift
- Liberapay
Зайдите в панель управления пакетами и раскройте блок Sponsorship Links (Ссылки Спонсорства). Добавьте ссылку, система автоматически проверит URL. После добавления ссылок значок
На данный момент поддерживаются только перечисленные платформы, и NuGet.org не собирает никакой статистики или финансовой информации о спонсорстве. Всё это отдано на откуп этим платформам.
Источник: https://devblogs.microsoft.com/dotnet/announcing-sponsorship-on-nugetdotorg-for-maintainer-appreciation/
Спонсорство на NuGet.org
NuGet.org теперь позволяет авторам пакетов добавлять URL спонсорства. Эта ссылка отображается в виде значка ❤️ или кнопки Sponsor this package (Спонсировать этот пакет) на странице пакета, направляя пользователей к безопасным и популярным платформам.
Пользователи пакетов теперь смогут поддерживать любимые пакеты. Найдите значок
❤️ Sponsor на NuGet.org (см. картинку выше). Нажмите на него, чтобы посетить страницу спонсорства и внести свой вклад.Для владельцев пакетов
Чтобы установить спонсорство для пакета:
1. вы должны быть владельцем или совладельцем пакета на NuGet.org;
2. спонсорская ссылка должна быть на одну из одобренных платформ:
- GitHub Sponsors
- Patreon
- Open Collective
- Ko-fi
- Tidelift
- Liberapay
Зайдите в панель управления пакетами и раскройте блок Sponsorship Links (Ссылки Спонсорства). Добавьте ссылку, система автоматически проверит URL. После добавления ссылок значок
❤️ Sponsor появится на странице пакета.На данный момент поддерживаются только перечисленные платформы, и NuGet.org не собирает никакой статистики или финансовой информации о спонсорстве. Всё это отдано на откуп этим платформам.
Источник: https://devblogs.microsoft.com/dotnet/announcing-sponsorship-on-nugetdotorg-for-maintainer-appreciation/
👍7
День 2462. #ЗаметкиНаПолях
Динамический LINQ. Начало
Вы реализуете простую конечную точку поиска… а затем приходит таска: «А можно отфильтровать по статусу? По последнему входу в систему? Сортировать по любому столбцу?» и т.п. И вот ваш красивый LINQ-запрос превращается в лес if, а каждое изменение означает повторное развёртывание. Знакомо? Рассмотрим динамические предикаты, которые выполняются как настоящий LINQ (поэтому EF Core транслирует их в SQL): как они работают, когда использовать и несколько полезных советов.
Зачем?
- Неограниченные фильтры: интерфейсы администратора, конструкторы отчётов, сохранённые поисковые запросы — пользователи сами выбирают поля/операции.
- Разные тенанты: каждому клиенту нужны немного разные правила.
- Сохранение производительности EF: библиотека преобразует строку в лямбда-выражение и вызывает реальный метод LINQ (Where, OrderBy, …) для IQueryable; EF по-прежнему перекладывает работу на SQL.
Как работает?
С помощью C# Eval Expression вы можете предоставить выражение в виде строки и вызвать динамическое расширение: WhereDynamic, OrderByDynamic, SelectDynamic, FirstOrDefaultDynamic и т.д. Внутри библиотеки оно преобразуется в дерево выражений и вызывается фактический оператор LINQ. Это работает для IEnumerable и IQueryable (включая EF Core).
Мы рассмотрим некоторые самые распространённые варианты использования:
- WhereDynamic — динамическая фильтрация,
- OrderByDynamic/ThenByDynamic — динамическая сортировка,
- SelectDynamic — динамическая проекция,
- FirstOrDefaultDynamic — динамическое извлечение единичных значений.
1. WhereDynamic
До: куча условных блоков
После: один динамический предикат
Почему это лучше: один конвейер, отсутствие дублирующихся запросов, и вы можете добавлять необязательные критерии, не изменяя форму запроса.
Кстати, не обязательно вставлять литералы в строку. Передайте объект контекста (анонимный тип/словарь/expando/класс) и ссылайтесь на его свойства по имени внутри выражения:
Окончание следует…
Источник: https://thecodeman.net/posts/dynamic-linq-in-dotnet
Динамический LINQ. Начало
Вы реализуете простую конечную точку поиска… а затем приходит таска: «А можно отфильтровать по статусу? По последнему входу в систему? Сортировать по любому столбцу?» и т.п. И вот ваш красивый LINQ-запрос превращается в лес if, а каждое изменение означает повторное развёртывание. Знакомо? Рассмотрим динамические предикаты, которые выполняются как настоящий LINQ (поэтому EF Core транслирует их в SQL): как они работают, когда использовать и несколько полезных советов.
Зачем?
- Неограниченные фильтры: интерфейсы администратора, конструкторы отчётов, сохранённые поисковые запросы — пользователи сами выбирают поля/операции.
- Разные тенанты: каждому клиенту нужны немного разные правила.
- Сохранение производительности EF: библиотека преобразует строку в лямбда-выражение и вызывает реальный метод LINQ (Where, OrderBy, …) для IQueryable; EF по-прежнему перекладывает работу на SQL.
Как работает?
С помощью C# Eval Expression вы можете предоставить выражение в виде строки и вызвать динамическое расширение: WhereDynamic, OrderByDynamic, SelectDynamic, FirstOrDefaultDynamic и т.д. Внутри библиотеки оно преобразуется в дерево выражений и вызывается фактический оператор LINQ. Это работает для IEnumerable и IQueryable (включая EF Core).
Мы рассмотрим некоторые самые распространённые варианты использования:
- WhereDynamic — динамическая фильтрация,
- OrderByDynamic/ThenByDynamic — динамическая сортировка,
- SelectDynamic — динамическая проекция,
- FirstOrDefaultDynamic — динамическое извлечение единичных значений.
1. WhereDynamic
До: куча условных блоков
var q = context.Customers.AsQueryable();
if (onlyActive)
q = q.Where(x => x.Status == CustomerStatus.IsActive);
if (since != null)
q = q.Where(x => x.LastLogon >= since);
if (!string.IsNullOrWhiteSpace(search))
q = q.Where(x => x.Name.Contains(search));
var list = await q.OrderBy(x => x.Name).ToListAsync();
После: один динамический предикат
// using System.Linq;
// using Z.Expressions;
string filter = "x => true";
if (onlyActive)
filter += " && x.Status == 0";
if (since != null)
filter += $@" && x.LastLogon >= DateTime.Parse(""{since:yyyy-MM-dd}"")";
if (!string.IsNullOrWhiteSpace(search))
filter += $@" && x.Name.Contains(""{search}"")";
var list = await context.Customers
.WhereDynamic(filter)
.OrderBy(x => x.Name)
.ToListAsync();
Почему это лучше: один конвейер, отсутствие дублирующихся запросов, и вы можете добавлять необязательные критерии, не изменяя форму запроса.
Кстати, не обязательно вставлять литералы в строку. Передайте объект контекста (анонимный тип/словарь/expando/класс) и ссылайтесь на его свойства по имени внутри выражения:
var env = new {
IsActive = CustomerStatus.IsActive,
LastMonth = DateTime.Now.AddMonths(-1)
};
var recentActive = await context.Customers
.WhereDynamic(x => "x.Status == IsActive
&& x.LastLogon >= LastMonth", env)
.ToListAsync();Окончание следует…
Источник: https://thecodeman.net/posts/dynamic-linq-in-dotnet
👎24👍6
День 2463. #ЗаметкиНаПолях
Динамический LINQ. Окончание
Начало
2. OrderByDynamic/ThenByDynamic
Даём пользователю возможность отсортировать результаты по любой колонке (из белого списка).
3. SelectDynamic
Для сценариев отчётов/экспорта, выдаём только то, что запросил клиент:
4. FirstOrDefaultDynamic
Идеален для поиска одного элемента или валидации на основе критерия, определяющегося во время выполнения:
Бонус: Цепочки динамических конвейеров
Если очень нужно выполнить несколько шагов LINQ в одной динамической строке (фильтрация → упорядочивание → выборка → список), есть API Execute:
Это мощный метод, но код получается не особо читаемый.
Варианты использования
1. Администрирование «Конструктор запросов»
- UI генерирует: поле + оператор + значение;
- Бэкенд выбирает разрешённые поля/операции → строит WhereDynamic (и опционально OrderByDynamic);
- Результат: один конвейер запросов, почти бесконечное количество комбинаций.
2. Маркетинг «Конструктор сегментов»
- Сегменты сохраняются как читаемые выражения (например, «Активные, последние 90 дней,>$500,не тестовые аккаунты»);
- Приложение загружает правило → WhereDynamic → сохраняет результаты;
- Результат: правила развиваются без изменения кода или повторного развёртывания.
3. Многопользовательские правила
- Каждый пользователь хранит несколько предикатов (или базовых фильтров разрешения/запрета);
- Они комбинируются во время запроса и применяются динамически;
- Результат: меньше ветвлений/флагов, более чистая модель.
Замечания
- Белый список полей/операторов: не раскрывайте всю модель; предоставьте в UI только разрешённый список.
- Проверка выражений: отклоняйте неизвестные токены/поля перед выполнением.
- IQueryable до конца: применяйте динамические операции перед ToList(), чтобы EF мог преобразовать их в SQL.
- Нормализуйте значения: используйте даты ISO или параметры (объект env) вместо парсинга текста.
- Сохраняйте читаемость: предпочитайте короткие, компонуемые строки; добавляйте вспомогательные методы для частых случаев.
Когда не использовать
Если у вас 2-3 фиксированных фильтра, которые редко меняются, статический LINQ остается самым простым (и вполне приемлемым). Динамический LINQ имеет смысл при росте изменчивости и опциональности.
Источник: https://thecodeman.net/posts/dynamic-linq-in-dotnet
Динамический LINQ. Окончание
Начало
2. OrderByDynamic/ThenByDynamic
Даём пользователю возможность отсортировать результаты по любой колонке (из белого списка).
var sort = sortCol switch
{
"LastLogon" => "x => x.LastLogon",
"TotalSpent" => "x => x.TotalSpent",
_ => "x => x.Name"
};
var ordered = await context.Customers
.OrderByDynamic(sort)
.ThenByDynamic("x => x.Id")
.ToListAsync();
3. SelectDynamic
Для сценариев отчётов/экспорта, выдаём только то, что запросил клиент:
// Клиент выбрал: "Id,Name,Country"
var cols = selectedCols.Split(',')
.Select(c => c.Trim())
.Where(c => allowedCols.Contains(c));
var selectExpr = "x => new { "
+ string.Join(", ", cols.Select(c => $"{c} = x.{c}"))
+ " }";
var result = await context.Customers
.WhereDynamic("x => x.Status == 0")
.SelectDynamic(selectExpr)
.ToListAsync();
4. FirstOrDefaultDynamic
Идеален для поиска одного элемента или валидации на основе критерия, определяющегося во время выполнения:
csharp
var result = await context.Customers
.FirstOrDefaultDynamic(
"x => x.Email == \\\"name@mail.com\\\" && x.Status == 0");
Бонус: Цепочки динамических конвейеров
Если очень нужно выполнить несколько шагов LINQ в одной динамической строке (фильтрация → упорядочивание → выборка → список), есть API Execute:
var env = new {
IsActive = CustomerStatus.IsActive,
LastMonth = DateTime.Now.AddMonths(-1) };
var result = context.Customers.Execute<IEnumerable>(
"Where(x => x.Status == IsActive && x.LastLogon >= LastMonth)" +
".Select(x => new { x.CustomerID, x.Name })" +
".OrderBy(x => x.CustomerID).ToList()", env);Это мощный метод, но код получается не особо читаемый.
Варианты использования
1. Администрирование «Конструктор запросов»
- UI генерирует: поле + оператор + значение;
- Бэкенд выбирает разрешённые поля/операции → строит WhereDynamic (и опционально OrderByDynamic);
- Результат: один конвейер запросов, почти бесконечное количество комбинаций.
2. Маркетинг «Конструктор сегментов»
- Сегменты сохраняются как читаемые выражения (например, «Активные, последние 90 дней,>$500,не тестовые аккаунты»);
- Приложение загружает правило → WhereDynamic → сохраняет результаты;
- Результат: правила развиваются без изменения кода или повторного развёртывания.
3. Многопользовательские правила
- Каждый пользователь хранит несколько предикатов (или базовых фильтров разрешения/запрета);
- Они комбинируются во время запроса и применяются динамически;
- Результат: меньше ветвлений/флагов, более чистая модель.
Замечания
- Белый список полей/операторов: не раскрывайте всю модель; предоставьте в UI только разрешённый список.
- Проверка выражений: отклоняйте неизвестные токены/поля перед выполнением.
- IQueryable до конца: применяйте динамические операции перед ToList(), чтобы EF мог преобразовать их в SQL.
- Нормализуйте значения: используйте даты ISO или параметры (объект env) вместо парсинга текста.
- Сохраняйте читаемость: предпочитайте короткие, компонуемые строки; добавляйте вспомогательные методы для частых случаев.
Когда не использовать
Если у вас 2-3 фиксированных фильтра, которые редко меняются, статический LINQ остается самым простым (и вполне приемлемым). Динамический LINQ имеет смысл при росте изменчивости и опциональности.
Источник: https://thecodeman.net/posts/dynamic-linq-in-dotnet
👍7👎1
День 2464. #ЗаметкиНаПолях
Потокобезопасная Инициализация с Помощью LazyInitializer
Хотя Lazy<T> является основным решением для ленивой инициализации в .NET, существует менее известная альтернатива, которая может быть более эффективной в некоторых сценариях: LazyInitializer.EnsureInitialized.
Этот статический метод обеспечивает потокобезопасную инициализацию с рядом ключевых характеристик:
- Только ссылочные типы: работает только с классами, но не со значениями.
- Обнаружение на основе NULL: использует значение NULL для определения необходимости инициализации.
- Эффективное использование памяти по сравнению с System.Lazy<T>: не требуется дополнительный объект-обёртка.
Метод предлагает несколько перегрузок для различных сценариев:
Замечания по потокобезопасности
По умолчанию LazyInitializer.EnsureInitialized ведёт себя как LazyThreadSafetyMode.PublicationOnly:
Несколько потоков могут создавать экземпляры одновременно. Сохраняется только первое успешное назначение. Остальные экземпляры отбрасываются.
Для строгой потокобезопасности используйте перегрузку с блокировкой синхронизации, чтобы гарантировать, что фабричный метод будет выполнен только один раз.
Внутренняя реализация этого аналогична следующему коду:
Преимущества
Главное преимущество перед Lazy<T> — вместо хранения объекта-обёртки Lazy<T> вы напрямую используете целевой экземпляр. Также это снижает затраты памяти, экономя одно поле на каждое лениво инициализированное значение.
Источник: https://www.meziantou.net/thread-safe-initialization-with-lazyinitializer.htm
Потокобезопасная Инициализация с Помощью LazyInitializer
Хотя Lazy<T> является основным решением для ленивой инициализации в .NET, существует менее известная альтернатива, которая может быть более эффективной в некоторых сценариях: LazyInitializer.EnsureInitialized.
Этот статический метод обеспечивает потокобезопасную инициализацию с рядом ключевых характеристик:
- Только ссылочные типы: работает только с классами, но не со значениями.
- Обнаружение на основе NULL: использует значение NULL для определения необходимости инициализации.
- Эффективное использование памяти по сравнению с System.Lazy<T>: не требуется дополнительный объект-обёртка.
Метод предлагает несколько перегрузок для различных сценариев:
Sample? _instance = null;
// Инициализация через конструктор по умолчанию
var instance =
LazyInitializer.EnsureInitialized(ref _instance);
// Фабричный метод
var instance =
LazyInitializer.EnsureInitialized(
ref _instance,
() => new Sample()
);
// Фабричный метод вызывается 1 раз, даже если нескольким потокам требуется инициализация
var syncLock = new object();
var instance =
LazyInitializer.EnsureInitialized(
ref _instance,
ref syncLock,
() => new Sample()
);
Замечания по потокобезопасности
По умолчанию LazyInitializer.EnsureInitialized ведёт себя как LazyThreadSafetyMode.PublicationOnly:
Несколько потоков могут создавать экземпляры одновременно. Сохраняется только первое успешное назначение. Остальные экземпляры отбрасываются.
Для строгой потокобезопасности используйте перегрузку с блокировкой синхронизации, чтобы гарантировать, что фабричный метод будет выполнен только один раз.
Внутренняя реализация этого аналогична следующему коду:
var instance = Volatile.Read(ref _instance) ??
Interlocked.CompareExchange(
ref _instance,
new Sample(),
null);
Преимущества
Главное преимущество перед Lazy<T> — вместо хранения объекта-обёртки Lazy<T> вы напрямую используете целевой экземпляр. Также это снижает затраты памяти, экономя одно поле на каждое лениво инициализированное значение.
Источник: https://www.meziantou.net/thread-safe-initialization-with-lazyinitializer.htm
👍12
День 2465.
Расширение Upgrade Assistant Недоступно в VS 17.14
Решили мы всё-таки начать обновляться с нашего .NET Framework до чего-то более современного. 🥳 Глядишь, где-нибудь к 12му .NET может и успеем. Но сейчас не об этом.
Я с удивлением обнаружил, что после последнего обновления в Visual Studio 2022 (версии 17.14) пропал пункт меню Upgrade, который вызывал расширение Upgrade Assistant.
Оказывается, расширение не поддерживается в версиях старше 17.13. Вместо этого появился пункт Modernize с иконкой Copilot. То есть вместо чёткого пошагового обновления предлагается отдать всё на откуп ИИ. Уже странное предложение. Но это ещё не всё. При попытке всё-таки начать обновление через Modernize, вылетает следующее сообщение:
GitHub Copilot app modernization is available exclusively to users on GitHub Copilot Pro, Pro+, Business, and Enterprise plans. For more details please refer to the documentation.
(Модернизация приложения GitHub Copilot доступна исключительно пользователям тарифных планов GitHub Copilot Pro, Pro+, Business и Enterprise. Подробнее см. в документации.)
То есть мало того, что не работает бесплатное работавшее раньше решение, так вместо него предлагается использовать недетерминированные ответы ИИ, да ещё только в платной подписке.
Стоит ли говорить, что у пользователей от такого нововведения серьёзно подгорело, и они стали строчить гневные отзывы в поддержку. Например, только в этом треде 128 постов.
В итоге в Microsoft сдали назад и вернули возможность использовать Upgrade Assistant. Для этого необходимо выполнить несколько шагов:
1. Удалить следующие расширения VS, если они имеются:
- Upgrade Assistant (.NET Upgrade Assistant - Visual Studio Marketplace)
- GitHub Copilot App Modernization – Upgrade for .NET (GitHub Copilot app modernization - upgrade for .NET - Visual Studio Marketplace)
- Azure Migrate Application and Code Assessment for .NET (Azure Migrate application and code assessment - Visual Studio Marketplace).
2. Перейти в Tools -> Options -> Projects and Solutions -> Modernization (Инструменты -> Настройки -> Проекты и Решения -> Модернизация) и установить Enable legacy Upgrade Assistant (Включить устаревший Помощник по Обновлению) в True.
3. Перезагрузить Visual Studio.
Расширение Upgrade Assistant Недоступно в VS 17.14
Решили мы всё-таки начать обновляться с нашего .NET Framework до чего-то более современного. 🥳 Глядишь, где-нибудь к 12му .NET может и успеем. Но сейчас не об этом.
Я с удивлением обнаружил, что после последнего обновления в Visual Studio 2022 (версии 17.14) пропал пункт меню Upgrade, который вызывал расширение Upgrade Assistant.
Оказывается, расширение не поддерживается в версиях старше 17.13. Вместо этого появился пункт Modernize с иконкой Copilot. То есть вместо чёткого пошагового обновления предлагается отдать всё на откуп ИИ. Уже странное предложение. Но это ещё не всё. При попытке всё-таки начать обновление через Modernize, вылетает следующее сообщение:
GitHub Copilot app modernization is available exclusively to users on GitHub Copilot Pro, Pro+, Business, and Enterprise plans. For more details please refer to the documentation.
(Модернизация приложения GitHub Copilot доступна исключительно пользователям тарифных планов GitHub Copilot Pro, Pro+, Business и Enterprise. Подробнее см. в документации.)
То есть мало того, что не работает бесплатное работавшее раньше решение, так вместо него предлагается использовать недетерминированные ответы ИИ, да ещё только в платной подписке.
Стоит ли говорить, что у пользователей от такого нововведения серьёзно подгорело, и они стали строчить гневные отзывы в поддержку. Например, только в этом треде 128 постов.
В итоге в Microsoft сдали назад и вернули возможность использовать Upgrade Assistant. Для этого необходимо выполнить несколько шагов:
1. Удалить следующие расширения VS, если они имеются:
- Upgrade Assistant (.NET Upgrade Assistant - Visual Studio Marketplace)
- GitHub Copilot App Modernization – Upgrade for .NET (GitHub Copilot app modernization - upgrade for .NET - Visual Studio Marketplace)
- Azure Migrate Application and Code Assessment for .NET (Azure Migrate application and code assessment - Visual Studio Marketplace).
2. Перейти в Tools -> Options -> Projects and Solutions -> Modernization (Инструменты -> Настройки -> Проекты и Решения -> Модернизация) и установить Enable legacy Upgrade Assistant (Включить устаревший Помощник по Обновлению) в True.
3. Перезагрузить Visual Studio.
👍28