C# (C Sharp) programming
18.1K subscribers
980 photos
52 videos
8 files
782 links
По всем вопросам- @notxxx1

Реестр РКН: https://clck.ru/3Fk3kb

#VRHSZ
Download Telegram
🕹️ NET-NES — эмулятор легендарной NES, написанный на C# и Raylib

После создания собственного эмулятора GameBoy (**CODE-DMG**), следующий шаг был очевиден — NES. Консоль, оставившая след не только в истории видеоигр, но и в электронике, вдохновила на создание нового проекта — NET-NES.

🎮 Что такое NET-NES?
Это NES-эмулятор, написанный на C# с использованием Raylib. Он уже способен запускать множество классических хитов от Nintendo.

📜 Немного истории:
• NES (Nintendo Entertainment System) — вышла в Японии как FamiCom в 1983 году
• В 1985 появилась в Северной Америке, где спасла индустрию после видеоигрового краха 1983 года
• Продавалась как "игрушка" — и изменила всё

🧠 Аппаратная часть NES:
• 8-битный CPU Ricoh 2A03 (~1.79 МГц), основанный на MOS 6502
• Встроенный APU (аудио)
• Видео: Ricoh 2C02 — вывод 256×240, палитра 64 цвета
• 2 КБ RAM + 2 КБ VRAM
• ROM‑картриджи с мапперами для расширения памяти и графики

🛠️ Почему C# и Raylib?
• Потому что C# — удобен, современен и любим
• Raylib — весёлый, минималистичный и идеально подходит для 2D-рендера
• А название NET-NES — от .NET и NES, звучит круто 😄


🔗 GitHub: github.com/Paulescu/NET-NES

#nes #dotnet #emulation #gamedev #csharp #retrogaming

@csharp_ci
⚙️ Background Jobs в ASP.NET Core — просто и эффективно

Хочешь запускать периодические задачи в фоне? В ASP.NET Core это можно реализовать с помощью BackgroundService и PeriodicTimer. Ни Hangfire, ни Quartz не нужны, если всё просто.

🧱 Основные шаги:

1. Включаем конкурентный запуск/остановку сервисов:

builder.Services.Configure<HostOptions>(o =>
{
o.ServicesStartConcurrently = true;
o.ServicesStopConcurrently = true;
});


2. 🌀 Реализуем фоновую задачу:

public class PeriodicBackgroundTask : BackgroundService
{
private readonly TimeSpan _period = TimeSpan.FromSeconds(5);
private readonly ILogger<PeriodicBackgroundTask> _logger;

public PeriodicBackgroundTask(ILogger<PeriodicBackgroundTask> logger)
{
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using PeriodicTimer timer = new PeriodicTimer(_period);
while (!stoppingToken.IsCancellationRequested &&
await timer.WaitForNextTickAsync(stoppingToken))
{
_logger.LogInformation("Executing PeriodicBackgroundTask");
}
}
}


📌 Особенности:
- BackgroundService — стандартный способ запускать фоновые задачи в ASP.NET Core
- PeriodicTimer — простой способ повторять с задержкой
- Встроенный контроль остановки через CancellationToken

💡 Подходит для:
• Регулярных проверок
• Очистки кэша
• Периодических sync-задач

#aspnetcore #dotnet #backgroundjobs #csharp #dev
📘 Обновлённый обзор C#: история версий и ключевые новшества

Microsoft опубликовала подробную хронологию C# — от версии 1.0 до последней, показывая эволюцию языка за 20+ лет:

🕰️ Обзор ключевых этапов:

C# 1.0–2.0 — классика: базовые ООП, exception-обработка, типы значений, generics
C# 3.0 — революция LINQ, lambda`-выражения, автоматические свойства, `var
C# 4.0dynamic, улучшения COM и переговорчивость аннотации
C# 5.0async/await — асинхронность для всех
C# 6.0 — улучшения синтаксиса: string interpolation, expression-bodied members, null-условные выражения
C# 7.xtuples, pattern matching, ref locals, out variables
C# 8.0 — nullable reference types, ranges/indices, асинхронные потоки
C# 9.0record, init-only properties, top-level statements
C# 10 — глобальные using, file-scoped namespace, улучшенные структуры
C# 11 — raw string literals, generic math, pattern matching improvements
C# 12 и далее — ожидаются расширенные метапрограммирование, списочные выражения, улучшения в безопасность и производительности

🔧 Почему это важно:

• Язык постоянно развивается, становясь выразительнее, безопаснее и удобнее
• Новые версии дают мощные инструменты — для асинхронного программирования, функционального стиля и более чистого кода
• Понимание изменений помогает быстрее адаптироваться к трендам и выбирать актуальный инструментальный стек

💡 Если вы разрабатываете на C#, стоит ознакомиться с историей версий — и понять, какие фичи уже доступны, а что стоит ожидать в будущем.

👉 Подробнее

@csharp_ci

#dotnet #csharp #programming #developer #language #whatsnew #technology
Microsoft.Extensions.AI (Preview) — единый способ подключать ИИ в .NET

Библиотеки Microsoft.Extensions.AI призваны упростить жизнь .NET-разработчикам, которые начинают использовать генеративный ИИ в своих приложениях.

🧱 Вместо разрозненных SDK для каждого провайдера — единые "AI building blocks", которые можно подключать и переключать между OpenAI, Azure, Hugging Face и другими.

📦 Что даёт:
– Единый интерфейс для разных AI-провайдеров
– Простая интеграция в pipeline .NET-приложения
– Расширяемая архитектура: можно добавлять собственные провайдеры
– Поддержка RAG-сценариев, чат-интерфейсов, промптинга, трансформаций данных и т.д.

Полезно и для ASP.NET-приложений, и для десктопа, и для фона.

🧪 Пока в превью — но уже можно попробовать:
https://github.com/dotnet/ai-samples?tab=readme-ov-file#microsoftextensionsai-preview

#dotnet #ai #ml #microsoft

@csharp_ci
🔥 Одна из дучших фишек в ASP.NET Core 10 — Server-Sent Events (SSE)

Теперь можно реализовать real-time обновления без SignalR и WebSockets. SSE — это лёгкий способ стримить данные с сервера на клиент *в одну сторону*, идеально для простых задач.

📡 Зачем это нужно?

В .NET-приложениях часто нужно передавать обновления с backend на frontend. Есть несколько способов:

• Polling — клиент всё время спрашивает: «что нового?» (нагружает сервер)
• SignalR — bidirectional WebSockets, но избыточно для простых стримов
• SSE — простой и нативный способ отправлять обновления *односторонне*

Теперь SSE доступен прямо в .NET 10 (preview) и легко интегрируется с Minimal APIs.

🧠 Что сегодня показали:
— Как работает SSE и чем отличается от SignalR
— Как реализовать SSE endpoint с Minimal API
— Как тестировать SSE-поток из IDE (HTTP request file)
— Как собрать frontend для отображения стриминга
— И как создать *живой рынок акций* на SSE — от бэкенда до клиента

👨‍💻 Отличная альтернатива, если нужно real-time, но без всей сложности WebSockets.

#dotnet #aspnetcore #SSE #ServerSentEvents #SignalR #realtime #webdev
.NET 9 — самая быстрая платформа 2025 года

Microsoft прокачала .NET так, что он обгоняет почти все популярные фреймворки: Java, Go, Node.js, Python и даже PHP.

🚀 Что сделали:
- Мусорщик (GC) стал адаптивным → меньше пауз даже при высоких нагрузках.
- JIT-компилятор быстрее разогревает код и оптимизирует горячие участки.
- Векторизация через AVX10 и Arm SVE ускоряет циклы в несколько раз.
- Native AOT уменьшает размер бинарников и ускоряет запуск (контейнеры, IoT, edge).
- Сеть (сокеты, HTTP/3) стала работать быстрее с низкой задержкой.
- JSON обрабатывается через System.Text.Json максимально эффективно.
- Меньше аллокаций → меньше нагрузка на память и GC.
- Thread-pool и многопоточность лучше распределяют задачи по ядрам.
- Минимальные API и оптимизация исключений дали ещё +15% к скорости.

📊 Бенчмарки показывают:
- Java (Spring) — медленнее в 2.5 раза
- Go (Fiber) — в 1.3 раза
- Node.js (Fastify) — в 4 раза
- Python (FastAPI) — в 10 раз
- PHP (Laravel) — в 15 раз
- Ruby (Rails) — в 20 раз

💡 Итог: .NET 9 — быстрый старт, низкая задержка и топ-производительность. Отличный выбор для веба, микросервисов и облака.

#dotnet #performance #benchmark #backend
Exceptions ≠ Errors

Многие разработчики путают эти понятия и проектируют приложения неправильно. Давайте разберём:

Что такое исключение (exception)?
Это ситуация, из которой приложение не может восстановиться.
Пример: критическая ошибка базы данных, повреждённый файл конфигурации.

Что такое ошибка (error)?
Это ожидаемое состояние сбоя или невыполненное предусловие.
Пример: пользователь ввёл неверный пароль, файл не найден, запрос не прошёл валидацию.

👉 Использовать исключения вместо ошибок = анти-паттерн. Так появляется flow control через исключения, который делает код непредсказуемым и запутанным.

Как правильно:
- Ошибки представляем явно в коде (например, через Result, Option, Either паттерны).
- Исключения оставляем для действительно неожиданных и фатальных ситуаций.

Бонус: Явные ошибки делают намерения кода прозрачными и облегчают поддержку.

📖 Подробнее: https://milanjovanovic.tech/blog/functional-error-handling-in-dotnet-with-the-result-pattern

#dotnet #cleanCode #architecture
⚙️ 3 способа определить Middleware в ASP.NET Core

Middleware - это компоненты, которые добавляют дополнительную логику до или после обработки HTTP-запроса.

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

🔧 В ASP.NET Core уже встроено множество middleware (Static Files, Routing, Authentication и др.),
но вы можете создавать и свои собственные.

Вот три основных способа это сделать:
- Request Delegates - определяете логику прямо в app.Use(...)
- Convention-based - создаёте класс с методом Invoke или InvokeAsync
- Factory-based - используете фабрику с внедрением зависимостей (DI)

🧠 Подробный разбор и примеры кода - в статье


#dotnet #aspnetcore #backend #middleware #csharp
🔥 EF Core 10 принес нормальные JOIN'ы в LINQ

Больше не нужно вспоминать, как извращаться с GroupJoin + DefaultIfEmpty, чтобы сделать обычный LEFT JOIN.
Теперь есть прямые методы:

LeftJoin
RightJoin

И они делают ровно то, что ты пишешь:
«Оставь все из левой таблицы и подтяни правые записи, если есть совпадения».

Плюсы
- Читаемость выше
- Код короче и очевиднее
- Транслируется в тот же SQL, что и раньше, но без боли

Примерно так LINQ наконец становится ближе к привычному SQL-пониманию разработчика: пишешь join — получаешь join, без магии и обходных путей.

Подробнее про LeftJoin и RightJoin в EF Core 10


#dotnet #efcore #csharp #linq #backend #devtools
🧠 EF Core и Repository: когда паттерн мешает, а не помогает

👶 Junior: использует EF Core прямо в контроллере
🧑 Middle: строит BaseRepository, IUnitOfWork, IOrderRepository, IOrderDataAccess...
🧓 Senior: снова использует EF Core — без репозиториев

Почему так?

Сначала Repository Pattern кажется удобным:
4 метода на CRUD — всё аккуратно.
Но как только домен растёт, появляются проблемы:

- Репозиторий на каждую сущность
- Общая логика между сущностями? Куда её девать?
- Репозитории раздуваются до 10+ методов
- Тестируемость становится фикцией: мокаем абстракцию от абстракции

А что насчёт "мы вдруг сменим базу"?

В 99% случаев — не смените.
EF Core и так абстрагирует SQL.
А при переходе на NoSQL придётся переписывать модели, запросы и подход целиком.

А что с "это улучшает разделение ответственности"?

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

DbContext уже реализует Repository и Unit of Work.
И это официально указано в исходниках EF Core.

🔥 17 000+ разработчиков уже ушли от репозиториев к практичному использованию EF Core в:
- N-Layered архитектуре
- Clean Architecture
- Vertical Slice
- Specification Pattern
- Интеграционных тестах с in-memory

📖 Подробнее:
https://antondevtips.com/blog/why-you-dont-need-a-repository-in-ef-core

#dotnet #efcore #architecture #backend #repositorypattern
🛡️ Новая обработка ошибок в .NET 10 - `IExceptionHandler`

Обрабатывать исключения теперь можно гибко, читаемо и без хаоса.

В .NET 10 появился интерфейс IExceptionHandler, который реализует паттерн try- прямо внутри middleware.

### Как это работает?

Ты сам указываешь, какие типы исключений хочешь перехватывать
Если ты обработал ошибку — возвращаешь true, и цепочка остановится
Можно выстроить несколько обработчиков подряд — они вызовутся по очереди, пока один не справится

📦 Это больше не про громоздкие try-catch или тонны if — теперь всё централизовано и масштабируемо.

🔧 Идеально для:
- Глобальной обработки ошибок
- Разделения логики по типам исключений
- Подключения к логгерам, метрикам, retry-логике

📚 Пример кода и объяснение:


Подходит всем, кто пишет на ASP.NET Core или строит APIЭ

#dotnet #aspnetcore #обработкаошибок #middleware #backend #csharp
⚡️ В мире #dotnet есть куда больше вариантов для messaging, чем RabbitMQ и Kafka.

И для real-time систем эти инструменты часто избыточны.

Большинство брокеров сообщений заточены под надёжность, сложную маршрутизацию и enterprise-сценарии.
Это отлично, когда нужны гарантии доставки и сложные пайплайны.
Но если система живёт на частых событиях, минимальной задержке и мгновенной реакции, этот вес начинает мешать.

Здесь идеально заходит NATS.

NATS - лёгкая и сверхбыстрая система обмена сообщениями, спроектированная именно для real-time:
- минимальная латентность
- простая модель
- высокая масштабируемость

Отлично подходит для:
- телеметрии и sensor data
- live-обновлений
- edge-систем
- сценариев, где важно «сейчас», а не «через секунду»

В статье подробно разобрано:
- когда NATS имеет смысл (а когда нет)
- сравнение с RabbitMQ и Kafka
- использование NATS в .NET с понятными примерами кода
- Pub/Sub, queue groups и request–reply

https://thecodeman.net/posts/introduction-to-nats-real-time-messaging
Интеграционные тесты прямо в CI/CD - максимум уверенности в коде 🚀

Я запускаю интеграционные тесты прямо внутри CI/CD пайплайна.
Так я проверяю не абстракции и моки, а реальное поведение системы.

Всё это возможно благодаря:
- Docker
- Testcontainers

Идея простая:
ты поднимаешь реальные внешние сервисы как контейнеры и используешь их прямо в тестах.

В примере поднимаются:
- PostgreSQL
- Redis
- Keycloak

Контейнеры:
- автоматически стартуют перед тестами
- доступны из кода приложения
- уничтожаются после выполнения тестов

Почему это работает лучше моков:
- тесты максимально близки к продакшену
- одинаковое поведение локально и в CI
- сразу ловятся проблемы с конфигурацией, миграциями, auth
- меньше сюрпризов после деплоя

Особенно полезно для:
- backend-сервисов
- микросервисной архитектуры
- систем с авторизацией и внешними зависимостями
- .NET-приложений с серьёзной бизнес-логикой

Если хочешь вывести интеграционное тестирование в .NET на новый уровень — Testcontainers стоит попробовать обязательно.

#dotnet, #testing
Перестань падать из-за одного внешнего API - добавь Fallback в .NET через Resilience Pipeline 🛡️

Вместо того чтобы приложение валилось, когда GitHub (или любой сервис) не отвечает, ты можешь вернуть безопасный дефолт и продолжить работу.

Идея простая:
Ты добавляешь fallback-стратегию в pipeline, и если запрос падает — система вернёт запасной результат.

Что происходит в примере:

— В DI регистрируется Resilience Pipeline
— Добавляется FallbackStrategy
— Если вызов неудачный, возвращается GitHubUser.Empty вместо исключения

Дальше в endpoint ты не вызываешь HttpClient напрямую — ты запускаешь его через pipeline:

pipeline.ExecuteAsync(...)

И если API:
упало
вернуло ошибку
словило таймаут

Пользователь не увидит 500. Он получит контролируемый ответ.

Это особенно важно для:
- внешних API
- микросервисов
- нестабильных сетей
- интеграций с SaaS

Fallback — это не про «скрыть ошибку».
Это про graceful degradation, когда система продолжает жить даже при частичных сбоях.

Надёжность — это архитектура, а не try/catch в каждом методе.
#dotnet #backend #architecture
💡 Soft delete в EF Core без лишней логики в сервисах

Удалять данные физически — не всегда хорошая идея.
Логи, аудит, восстановление, аналитика — всё это требует soft delete.

Вот удобный способ реализовать его через EF Core interceptor.

Что делает перехватчик:

- Проверяет ChangeTracker на сущности с интерфейсом ISoftDeletable
- Если состояние сущности — Deleted
- Меняет его на Modified
- Устанавливает:
- IsDeleted = true
- DeletedOnUtc = DateTime.UtcNow

В итоге:

Вы вызываете обычный:

context.Remove(entity);


А в базе:

- запись не удаляется
- просто помечается как удалённая

Плюсы подхода:

- никакой логики soft delete в сервисах и репозиториях
- единая точка обработки
- чистый доменный код
- безопасное удаление по всему приложению

Важно:

Если у вас есть связанные сущности (navigation properties),
перехватчик нужно дополнительно расширить — каскадное soft-удаление EF Core не делает автоматически.

Soft delete через interceptor — это один из самых чистых production-подходов для EF Core.

#dotnet #EFCore #Backend #Architecture #CSharp
Разработчик показал, как использовать Ollama для извлечения данных из чеков прямо в .NET.

Самая интересная часть оказалась не в том, чтобы отправить изображение модели.

Гораздо сложнее было получить результат, который можно реально использовать в коде.

Обычный текстовый ответ мало помогает, когда нужны структурированные данные:

- позиции из чека
- количество
- цены
- итоговая сумма

Поэтому вместо обычного ответа модель начали просить возвращать JSON.

После этого результат можно сразу маппить в C#-объекты и использовать в приложении.

И именно здесь начинается самое интересное.

Большая часть работы — не код, а правильный prompt.

Если модель:

- округляла цену
- пропускала цифру
- или «придумывала» позицию

приходилось уточнять инструкции.

Это и есть главный сдвиг в таком подходе:

раньше разработчик писал парсеры и regex,
а теперь — настраивает поведение модели через prompt.

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

Разбор полной реализации:

https://milanjovanovic.tech/blog/how-to-extract-structured-data-from-images-using-ollama-in-dotnet

🚀 Max

#ai #ollama #dotnet #csharp
🐳 «Используй Testcontainers вместо in-memory» - это только половина правды

Все уже выучили: EF Core InMemory provider - не интеграционный тест.

Он не ловит:

- баги в LINQ-трансляции
- ограничения БД
- коллации
- реальные типы колонок
- поведение конкретного SQL-провайдера

Окей, заменили на реальный PostgreSQL через Testcontainers. Победа? Не совсем.

Вот что начинается дальше.

1. Вы получили «медленное враньё» вместо «быстрого»

Поднимать контейнер на каждый тест-класс - быстрый способ превратить CI из 30 секунд в 8 минут.

Нормальный вариант:

- один контейнер на всю тестовую сессию
- изоляция данных между тестами через Respawn
- без пересоздания базы и контейнера каждый раз

Respawn чистит таблицы с учётом графа foreign keys за миллисекунды.

2. Транзакционный откат ≠ реальный сценарий

Трюк «обернули тест в транзакцию и откатили» красиво выглядит, но ломается, когда в коде есть:

- свои транзакции
- несколько SaveChanges
- фоновые операции
- поведение, завязанное на commit

В итоге тестируется сценарий, которого в проде нет.

3. Самая коварная ловушка - общий DbContext

Если тест и код используют один экземпляр DbContext, EF может вернуть данные из change tracker, а не из базы.

Тест зелёный, но он врёт: реальный SQL-запрос мог вообще не выполниться.

Между Act и Assert стоит чистить трекер:


Db.ChangeTracker.Clear();


4. Бонус, который теряют 90% команд - тест миграций

Реальная БД позволяет прогнать EF-миграции на чистой схеме.

Если миграция падает или схема разъехалась с моделью, вы узнаёте об этом в CI, а не в проде в пятницу вечером.

Пример базового подхода:


public class IntegrationTestBase : IAsyncLifetime
{
private static readonly PostgreSqlContainer _db =
new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
.Build();

private Respawner _respawner = null!;
protected AppDbContext Db = null!;

public async Task InitializeAsync()
{
await _db.StartAsync();

var options = new DbContextOptionsBuilder<AppDbContext>()
.UseNpgsql(_db.GetConnectionString())
.Options;

Db = new AppDbContext(options);

// Реальные миграции - заодно проверяем, что они накатываются
await Db.Database.MigrateAsync();

await using var conn = new NpgsqlConnection(_db.GetConnectionString());
await conn.OpenAsync();

_respawner = await Respawner.CreateAsync(conn, new RespawnerOptions
{
DbAdapter = DbAdapter.Postgres,
SchemasToInclude = ["public"]
});
}

// Сброс данных перед каждым тестом - без пересоздания контейнера
protected async Task ResetAsync()
{
await using var conn = new NpgsqlConnection(_db.GetConnectionString());
await conn.OpenAsync();

await _respawner.ResetAsync(conn);

// Иначе тест может читать из кеша, а не из БД
Db.ChangeTracker.Clear();
}

public Task DisposeAsync() => Task.CompletedTask;
}


Testcontainers - это не галочка «best practice», а смена философии.

Без нормальной изоляции данных вы просто пересели с быстрого вранья на медленное.

А как вы изолируете состояние БД между интеграционными тестами - Respawn, транзакции или пересоздание контейнера?

#dotnet #csharp #testing #efcore
⚡️ Почему Repository поверх EF Core часто превращается в лишний слой

Многие .NET-проекты начинают с отдельных репозиториев:


GetPostsByUser(...)
GetPopularPosts(...)
GetPostsByCategory(...)
GetRecentViralPosts(...)


Сначала всё выглядит аккуратно. Затем появляются новые фильтры, сортировки и бизнес-правила, а репозиторий разрастается до десятков похожих методов.

Проблема в том, что DbContext уже предоставляет возможности, близкие к Repository и Unit of Work. Дополнительный слой часто усложняет запросы, скрывает возможности EF Core и создаёт абстракцию поверх абстракции.

Один из вариантов решения — Specification Pattern.

Каждая спецификация описывает отдельное условие выборки:


var specification =
new ViralPostSpecification(minLikesCount: 150);

var posts = await dbContext.Posts
.ApplySpecification(specification)
.Select(post => post.ToDto())
.ToListAsync(cancellationToken);


Спецификации можно переиспользовать и комбинировать:


var combinedSpec =
recentSpec.And(highEngagementSpec);


Что это даёт:

- фильтры не размножаются по репозиториям
- запросы остаются рядом с бизнес-правилами
- спецификации проще тестировать
- условия можно комбинировать
- IQueryable продолжает переводиться в SQL

Repository Pattern полезен, когда действительно изолирует сложную инфраструктуру или несколько источников данных. Но создавать отдельный репозиторий для каждой сущности только ради шаблона часто означает лишнее усложнение архитектуры.

#dotnet #csharp #efcore #architecture
💡 C#: заставьте архитектуру ломать CI, если кто-то нарушил правила

Компилятор C# отлично проверяет типы, но ему всё равно, что Application внезапно начал зависеть от Infrastructure.

Code Review тоже не гарантирует, что такое заметят.

Для этого можно использовать Architecture Tests — тесты, которые проверяют не бизнес-логику, а структуру проекта.

Например, через NetArchTest.Rules:


[Fact]
public void Application_Should_Not_Depend_On_Infrastructure()
{
var result = Types
.InAssembly(ApplicationAssembly)
.ShouldNot()
.HaveDependencyOn("MyApp.Infrastructure")
.GetResult();

Assert.True(result.IsSuccessful);
}


Теперь случайный:


Application → Infrastructure


сломает CI так же, как обычный упавший unit-тест.

Можно зафиксировать и naming convention:


[Fact]
public void Handlers_Should_End_With_Handler()
{
var result = Types
.InAssembly(ApplicationAssembly)
.That()
.ImplementInterface(typeof(ICommandHandler<>))
.Should()
.HaveNameEndingWith("Handler")
.GetResult();

Assert.True(result.IsSuccessful);
}


Или заставить сервисы быть sealed:


Types
.InAssembly(ApplicationAssembly)
.That()
.HaveNameEndingWith("Service")
.Should()
.BeSealed();


Особенно полезно это становится в больших Clean Architecture / DDD / Modular Monolith проектах.

Вместо документа:


«Application не должен зависеть от Infrastructure»


получаем исполняемое правило:


нарушил архитектуру → тест упал → PR не прошёл


По сути, архитектура превращается из договорённости команды в часть автоматической проверки проекта.

#CSharp #DotNet #Architecture #Testing
Microsoft выпустила августовские servicing-обновления для .NET и .NET Framework

Обновления вышли 11 августа 2026 года и включают как security, так и non-security fixes.

Актуальные версии:

- .NET 10.0.11
- .NET 9.0.19
- .NET 8.0.30

В этом месяце Microsoft закрыла сразу несколько уязвимостей в .NET 8, 9 и 10, включая:

- Remote Code Execution
- Elevation of Privilege
- Information Disclosure
- Denial of Service
- Security Feature Bypass

Среди исправлений есть CVE-2026-70354 и CVE-2026-62897, связанные с удалённым выполнением кода.

Обновлены также:

- ASP.NET Core
- Entity Framework Core
- Runtime
- container images
- Linux packages

Для .NET Framework тоже вышли новые security и non-security updates.

Если приложение работает на .NET 8, 9 или 10, августовский servicing update лучше не откладывать, особенно из-за набора security fixes.

Подробнее:
https://devblogs.microsoft.com/dotnet/dotnet-and-dotnet-framework-august-2026-servicing-updates/

#aspnetcore #dotnet