C# (C Sharp) programming
18.6K subscribers
798 photos
41 videos
8 files
702 links
По всем вопросам- @haarrp

C# - обучающий канал Senior C# разработчика.

@ai_machinelearning_big_data - Machine learning

@itchannels_telegram - 🔥лучшие ит-каналы

@csharp_ci - C# академия

@pythonlbooks- книги📚

Реестр РКН: https://clck.ru/3Fk3kb
Download Telegram
🚫 EF Core + «репозитории» = лишний слой

Часто советуют заворачивать EF Core в Repository Pattern.
Но на практике это делает код только сложнее:

- DbContext уже реализует Repository и Unit of Work
- Репозитории со временем превращаются в «монстров» с десятками методов
- Каждый новый фильтр = новая копипаста

В итоге — абстракция над абстракцией и трудности с поддержкой.

---

Что вместо этого? Specification Pattern

Specification = маленький класс, описывающий правило или фильтр.
Вы комбинируете их и получаете сложные запросы без раздутых репозиториев.

Плюсы:
- 🧩 Простая композиция правил
- 🔍 Ясный и читаемый код
- ♻️ Повторное использование условий
- 🧪 Лёгкое тестирование

📌 Пример


// Бизнес-правило: активные клиенты с заказами за последние 30 дней
public sealed class ActiveCustomersSpec : Specification<Customer>
{
public ActiveCustomersSpec(DateTime since)
{
Criteria = c => c.IsActive && c.Orders.Any(o => o.CreatedAt >= since);
AddInclude(c => c.Orders);
}
}

// Применение
var spec = new ActiveCustomersSpec(DateTime.UtcNow.AddDays(-30));
var customers = await db.Set<Customer>().Apply(spec).ToListAsync();


💡 Итог:

EF Core = уже Repository + UoW

Репозитории поверх EF Core → лишняя абстракция

Specification Pattern → гибкость и читаемость без «метод-монстров»
Serilog.Sinks.XUnit3 👩‍💻

Пришло время рассказывать про свои библиотеки!

Если вы пишете тесты на xUnit.v3 и логгируете через Serilog, то моё решение для вас!


Каждый на работе сталкивался с непонятным багом. Смотришь в код и видишь фигу)

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

Логгирование призвано помочь разрабу справиться со страданиями, но вот незадача! При запуске интеграционного теста с воспроизведением бага логи никуда не выводятся.

Поэтому я написал Serilog.Sinks.XUnit3!
Чтобы не выходя из IDE разработчик понимал, что происходит!

Призываю вас делится этой библиотекой и внедрять в свои тесты!

👩‍💻 GitHub: https://github.com/Stepami/serilog-sinks-xunit-v3
👩‍💻 NuGet: https://www.nuget.org/packages/Serilog.Sinks.XUnit3
Please open Telegram to view this post
VIEW IN TELEGRAM
📝 TodoList gRPC: Упрощённый бэкенд для собеседований

Этот репозиторий представляет собой облегчённый форк проекта, созданного для проверки навыков кандидатов на собеседованиях. Он предоставляет чистый и компактный бэкенд на основе gRPC и ASP.NET, который используется для создания простого фронтенда, взаимодействующего с API.

🚀 Основные моменты:
- Легковесный бэкенд на C# и ASP.NET Core.
- Использует gRPC для взаимодействия с фронтендом.
- Поддерживает различные клиентские фреймворки.
- Идеален для технических собеседований и оценки навыков.

📌 GitHub: https://github.com/Steffen70/todolist-grpc

@csharp_ci
🚀 Git Pro совет

Хотите быстро узнать, какие файлы менялись чаще всего в репозитории?
Используйте встроенные возможности git log:


# Топ-10 самых часто меняемых файлов
git log --pretty=format: --name-only | \
sort | uniq -c | sort -nr | head -10


💡 Отличный способ найти "проблемные" файлы:
именно они чаще всего требуют правок и могут быть источником багов.
Что выведет на экран этот код?
Anonymous Quiz
15%
False, False
14%
False, True
30%
True, True
34%
True, False
6%
🥒
Better Database Design 💡

Чтобы повысить безопасность и упростить управление доступом, используйте логическую изоляцию с помощью схем.

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


CREATE SCHEMA Orders;
CREATE SCHEMA Shipping;

-- Orders module can only access its schema
CREATE USER OrdersUser WITH DEFAULT_SCHEMA = Orders;
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Orders TO OrdersUser;

-- Shipping module can only access its schema
CREATE USER ShippingUser WITH DEFAULT_SCHEMA = Shipping;
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Shipping TO ShippingUser;


Идея проста:
Создавайте отдельного пользователя для каждой схемы и используйте разные connection string в приложении. Это уменьшает риски и делает архитектуру чище.
🛡️ Запуск программ с защитой PPL

CreateProcessAsPPL — инструмент для запуска приложений с включенной защитой PPL. Позволяет выбирать уровень защиты для повышения безопасности выполнения программ.

🚀 Основные моменты:
- Поддержка нескольких уровней защиты PPL.
- Удобный интерфейс командной строки.
- Полезен для разработчиков и исследователей безопасности.

📌 GitHub: https://github.com/2x7EQ13/CreateProcessAsPPL

#csharp
🔍 ZeroTrace: Утечка данных из браузеров и мониторинг клиентов

ZeroTrace — это мощный инструмент для сбора и анализа данных с удалённых клиентских машин. Он поддерживает извлечение паролей, куки и историю браузера, обеспечивая безопасность и эффективность работы.

🚀 Основные моменты:
- Извлечение паролей и куки из Chrome и других браузеров
- Реальное время мониторинга клиентов с анализом соединений
- Безопасная передача данных с шифрованием
- Поддержка различных операционных систем и браузеров

📌 GitHub: https://github.com/luis22d/ZeroTrace-Stealer-13-2026

#csharp
Что выведет на экран этот код?
Anonymous Quiz
23%
False False
15%
False True
36%
True True
8%
True False
18%
🥒
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
⚡️ .NET-приложения должны быть устойчивыми — и сделать их надежнее реально за пару минут.

В .NET 8 и выше есть библиотеки от Microsoft и обновлённый API Polly — популярной библиотеки для повышения надёжности и обработки сбоев.

С Polly можно легко настроить стратегии:
- повтор запросов (Retry)
- резервные сценарии (Fallback)
- ограничение времени (Timeout)
- контроль частоты (Rate-limiting)
- автоматическое отключение при сбоях (Circuit breaker)

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

Подробный разбор тут
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Полезный ресурс, который содержит вопросы для подготовки к собеседованию по .NET!

🔗 Ссылка: *клик*

@csharp_ci
Please open Telegram to view this post
VIEW IN TELEGRAM
🧪 Как правильно строить unit-тестирование в проектах с Clean Architecture

Милан Йованович делится опытом: многие проекты терпят неудачу из-за слабого тестирования.
Когда кодовая база растёт, каждое изменение становится рискованным, а уверенность команды в релизах падает.

В Clean Architecture тестируемость — одна из ключевых идей. Unit-тесты позволяют убедиться, что use cases работают так, как задумано требованиями.

📌 Подход Милана к unit-тестированию:
- использовать NSubstitute для моков зависимостей
- проверять все happy paths
- покрывать все failure paths
- обязательно тестировать обработку исключений

Такой набор тестов помогает сохранить надёжность логики и уверенность в изменениях.

✍️ Подробный разбор с пошаговым объяснением можно прочитать в его статье
🛠️ Инструмент для дампа памяти защищённых процессов

WSASS использует старую программу WerfaultSecure.exe для создания дампов памяти процессов, защищённых PPL, таких как LSASS.EXE. Выходные данные сохраняются в формате MINIDUMP, с автоматической заменой заголовка на PNG для удобства.

🚀 Основные моменты:
- Дамп защищённых процессов с помощью WerfaultSecure.exe
- Выход в формате Windows MINIDUMP
- Автоматическая замена заголовка файла
- Полезен для анализа безопасности

📌 GitHub: https://github.com/TwoSevenOneT/WSASS

#csharp
В какой строке возникнет ПЕРВАЯ ошибка
Anonymous Quiz
40%
1
29%
2
10%
3
2%
4
18%
ошибки не возникнет
🪄 magictools — curated-подборка инструментов и ресурсов для разработки игр

Если ты занимаешься геймдевом — этот репозиторий настоящий клад для поиска подходящих инструментов! Вот что внутри:

- Графика: от placeholders до редакторов и генераторов персонажей
- Spritesheets и анимация: инструменты для упаковки и обработки
- Фреймворки и движки: 2D/3D, физика, GUI, звук, освещение, генерация ландшафта и кастомные пайплайны
- Аудио и музыка: коллекции звуков и редакторы
- Книги, видео, подкасты, журналы и блоги: образовательное и вдохновляющее содержание
- Game Jam сообщества, исходники игр, управление проектами — всё в одном месте!
- Плюс разделы по AI, обучению, инструментам общего развития и прочему ценному

Этот список постоянно растёт и обновляется — отличное решение, чтобы не запутаться в инструментариуме.

https://github.com/ellisonleao/magictools

#GameDev #Ресурсы #Инструменты
🧭 Зачем нужен service discovery?

Проблема микросервисов проста: как сервисам надёжно находить и вызывать друг друга? Жёстко прописанные IP и порты ломаются при любом масштабировании, перезапуске, автосборке или миграции.

Что делает service discovery
- Даёт логические имена вместо физических адресов (users-api, billing, auth).
- Динамически находит живые инстансы и балансирует запросы.
- Упрощает масштабирование, blue/green-деплой и отказоустойчивость.

Как это работает (базовый поток)
1) Сервис регистрируется в реестре (name → адреса, порты, метаданные, health).
2) Клиент запрашивает реестр и получает актуальный адрес.
3) Клиент шлёт запрос по полученному адресу (часто с ретраями и timeouts).

Паттерны
- Client-side discovery: клиент сам спрашивает реестр (Consul, Eureka).
- Server-side discovery: маршрутизация через прокси/ингресс (Envoy, API-шлюз).
- K8s-вариант: встроенный DNS/Services дают стабильные имена.

Что выбрать
- Consul/Eureka — когда вы не в Kubernetes или хотите гибкий реестр и health-чеки.
- K8s Services — когда всё крутится в Kubernetes.
- Envoy/Traefik/API-шлюз — если нужен серверный роутинг, канареечные релизы, mTLS.

Как внедрить в .NET (пример с Consul)
- Поднимите Consul-агент (dev/cluster), включите health-чеки (HTTP/TCP/TTL).
- Регистрируйте сервис на старте приложения: имя, адрес, порт, теги, check.
- Разрешайте адреса через:
- Consul API (client-side discovery в коде .NET),
- или DNS-запросы вида service-name.service.consul (удобно для простых клиентов),
- или через sidecar/Envoy, чтобы вынести логику сетевого стека из приложения.
- Добавьте политики устойчивости (Polly): retries, circuit breaker, timeouts.
- Пропишите deregistration при остановке, чтобы не висели «мертвые» инстансы.
- Логи/метрики: мониторьте failing-чеки, латентность и распределение трафика.

Пример в .NET:

builder.Services
.AddHttpClient<ReportingServiceClient>(client =>
{
client.BaseAddress = new Uri("https://reporting-service");
})
.AddServiceDiscovery()
.AddRoundRobinLoadBalancer();


Итог
Service discovery — это «телефонная книга» вашего продакшена. Без него микросервисы быстро превращаются в хрупкий клубок адресов и ручных костылей. В .NET связка Consul + health-чеки + политики устойчивости даёт простой и надёжный старт.

Для пошагового гайда по .NET и Consul ищите разбор Milan Jovanovic «Service discovery in microservices with .NET and Consul».
⚙️ Создание фоновых задач в .NET с Quartz

Если тебе нужно планировать фоновые задачи в .NET — попробуй Quartz.
Всё просто: реализуешь интерфейс, регистрируешь задачу — и Quartz берёт на себя расписание и выполнение.

Что делает Quartz удобным:
- Глубокая интеграция с Dependency Injection — можно внедрять сервисы, логеры и репозитории;
- Scoped-область задач — безопасно использовать DbContext без проблем с жизненным циклом;
- Умный планировщик: без ручных таймеров и бесконечных циклов.

После Quartz уже не хочется возвращаться к ручным решениям.

📘 Подробный гайд по продвинутой работе с Quartz в .NET