1.7Kпросмотров
25.5%от подписчиков
19 марта 2026 г.
statsScore: 1.9K
День 2605. #ЗаметкиНаПолях
5 Малоизвестных Функций C#, Которые Упростят Вашу Жизнь
Фреймворк уже имеет надёжные инструменты для решения различных проблем, но многие из них мало известны. Сегодня рассмотрим некоторые. 1. OperatingSystem.IsX вместо RuntimeInformation
В течение многих лет проверка текущей ОС в .NET означала написание чего-то вроде:
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ //…
}
Теперь появились более чистые варианты:
- OperatingSystem.IsWindows,
- OperatingSystem.IsLinux, - OperatingSystem.IsMacOS
и т.п.
if (OperatingSystem.IsWindows())
{ //…
} 2. Правильная изоляция плагинов с помощью AssemblyLoadContext
Если вы когда-либо пытались создать систему плагинов в .NET, вы знаете, насколько болезненны конфликты сборок. Загрузите две версии одной и той же зависимости, и внезапно всё перестаёт работать. AssemblyLoadContext позволяет загружать сборки изолированно, так что два плагина могут зависеть от разных версий одной и той же DLL, не мешая друг другу. Вот минимальный код для начала:
class PluginLoadContext : AssemblyLoadContext
{ private AssemblyDependencyResolver _resolver; public PluginLoadContext(string path) => _resolver = new(path); protected override Assembly? Load(AssemblyName name) { var path = _resolver .ResolveAssemblyToPath(name); return path != null ? LoadFromAssemblyPath(path) : null; }
}
Теперь каждый плагин существует в своей среде. Вы также можете их выгружать, что очень важно для длительно работающих процессов, таких как серверы. 3. Разбор зависимостей с помощью AssemblyDependencyResolver
AssemblyDependencyResolver, получив путь к плагину или сборке, определяет, откуда должны браться зависимости:
var resolver = new AssemblyDependencyResolver(pluginPath);
var path = resolver .ResolveAssemblyToPath(assemblyName);
Вы получаете правильные правила разрешения зависимостей, соответствующие тому, как это обычно делает .NET, но с областью действия в контексте плагина. Так вы избегаете неприятных сюрпризов, когда плагин ссылается на Newtonsoft.Json 13.0.1, а хост-приложение использует 12.0.3. 4. Получение версий сборок без ошибок
Часто в коде можно встретить что-то такое:
var version = Assembly .GetExecutingAssembly() .GetName() .Version;
Дело в том, что это значение не всегда совпадает с версией, которую вы указали в проекте. Это версия сборки, а не обязательно версия файла или информационная версия. Какая из них вам нужна?
- AssemblyName.Version - версия сборки, полученная во время компиляции,
- FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion - версия файла,
- AssemblyInformationalVersionAttribute - семантическая версия, вроде 1.0.0-beta+sha.abc123. Лучший подход – выражаться более явно:
var version = Assembly .GetExecutingAssembly() .GetCustomAttribute<AssemblyInformationalVersionAttribute>()? .InformationalVersion;
Так вы получите именно ту строку, которую хотели передать, а не то, что MSBuild по умолчанию присвоил вашей DLL. 5. Получение зависимостей из контейнера с помощью ActivatorUtilities
Иногда нужно создать объект, который не зарегистрирован в контейнере, но имеет зависимости, которые зарегистрированы. Используйте ActivatorUtilities:
var myService = ActivatorUtilities .CreateInstance<MyService>(serviceProvider);
Это говорит контейнеру: «Я знаю, что MyService не зарегистрирован, но, пожалуйста, внедри все необходимые ему сервисы». Это удобный обходной путь, который избавляет вас от необходимости создавать неудобные фабрики или засорять код логикой разрешения сервисов. Источник: https://blog.stackademic.com/if-youre-not-using-these-5-net-features-you-re-working-too-hard-0aefbf5a6fdc?gi=bb3ac273e638