Клас AssemblyLoadContext
у .NET Core та пізніших версіях
Клас AssemblyLoadContext
у .NET Core та пізніших версіях є механізмом для завантаження та керування збірками під час виконання. Він надає спосіб контролювати завантаження та вивантаження збірок, пропонуючи гнучкість для таких сценаріїв, як плагіни, динамічне завантаження та ізоляція.
1. Що таке AssemblyLoadContext
?
- Це еквівалент AppDomains у .NET Framework, але він фокусується конкретно на завантаженні та вивантаженні збірок.
- Кожен
AssemblyLoadContext
виступає як ізольований контекст для керування збірками та їхніми залежностями.
2. Чому варто використовувати AssemblyLoadContext
?
a. Розробка плагінів
Динамічно завантажуйте плагіни без впливу на основний додаток або інші плагіни.
b. Вивантаження збірок
Вивантажуйте збірки для звільнення пам'яті та ресурсів, коли вони більше не потрібні.
c. Ізоляція залежностей
Завантажуйте різні версії збірок або конфліктуючі залежності в окремі контексти.
d. Тестування та скрипти
Динамічно завантажуйте збірки під час тестування або виконання наданих користувачем скриптів.
3. Ключові функції AssemblyLoadContext
a. Стандартні та користувацькі контексти
- Стандартний контекст: стандартний контекст завантаження для додатка, зазвичай використовується для завантаження основних збірок додатка.
- Користувацький контекст: дозволяє створювати ізольовані контексти для завантаження збірок незалежно.
b. Вивантаження
Користувацькі контексти можуть вивантажувати збірки за допомогою збирання сміття після того, як не залишиться жодних посилань.
c. Розв'язання збірок
Налаштовувана логіка розв'язання для пошуку та завантаження збірок.
4. Створення та використання AssemblyLoadContext
Приклад 1: Динамічне завантаження збірки
Ось базовий приклад динамічного завантаження збірки з використанням користувацького AssemblyLoadContext
:
using System;
using System.Reflection;
using System.Runtime.Loader;
class CustomLoadContext : AssemblyLoadContext
{
protected override Assembly Load(AssemblyName assemblyName)
{
// Користувацька логіка для розв'язання збірки
Console.WriteLine($"Завантаження збірки: {assemblyName.FullName}");
return null; // Повертаємо null для використання стандартного розв'язання.
}
}
class Program
{
static void Main()
{
var context = new CustomLoadContext();
// Завантажуємо збірку з файлу
Assembly assembly = context.LoadFromAssemblyPath(@"C:\path\to\your\assembly.dll");
// Доступ до типів та членів збірки
Type type = assembly.GetType("Namespace.ClassName");
MethodInfo method = type.GetMethod("MethodName");
method.Invoke(null, null);
// Вивантаження контексту
context.Unload();
Console.WriteLine("Збірку вивантажено.");
}
}
5. Вивантаження збірок
Збірки, завантажені в користувацький AssemblyLoadContext
, можуть бути вивантажені, коли:
- Усі посилання на
AssemblyLoadContext
та його завантажені збірки звільнено. - Збірник сміття збирає
AssemblyLoadContext
.
Приклад: Вивантаження збірки
using System;
using System.Reflection;
using System.Runtime.Loader;
class Program
{
static void Main()
{
WeakReference contextReference = LoadAndUnloadAssembly();
// Примусове збирання сміття для вивантаження контексту
for (int i = 0; i < 10 && contextReference.IsAlive; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine(contextReference.IsAlive ? "Контекст все ще існує" : "Контекст вивантажено");
}
static WeakReference LoadAndUnloadAssembly()
{
var context = new AssemblyLoadContext("CustomContext", isCollectible: true);
Assembly assembly = context.LoadFromAssemblyPath(@"C:\path\to\your\assembly.dll");
// Створюємо WeakReference до контексту для моніторингу вивантаження
var weakReference = new WeakReference(context);
// Вивантажуємо контекст
context.Unload();
return weakReference;
}
}
## Розв'язання збірок у `AssemblyLoadContext`
### Користувацька логіка розв'язання
Ви можете перевизначити метод `Load`, щоб визначити власну логіку розв'язання збірок.
### Приклад: Розв'язання залежностей
using System;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
class CustomLoadContext : AssemblyLoadContext
{
private string dependencyPath;
public CustomLoadContext(string dependencyPath)
{
_dependencyPath = dependencyPath;
}
protected override Assembly Load(AssemblyName assemblyName)
{
string assemblyPath = Path.Combine(dependencyPath, assemblyName.Name + ".dll");
if (File.Exists(assemblyPath))
{
return LoadFromAssemblyPath(assemblyPath);
}
return null; // Використовуємо стандартне розв'язання, якщо не знайдено
}
}
class Program
{
static void Main()
{
var context =path\to\dependencies");
Assembly assembly = context.LoadFromAssemblyName(new AssemblyName("DependencyName"));
Console.WriteLine($"Завантажено збірку: {assembly.FullName}");
}
}
```
7. Кращі практики
- Використовуйте
isCollectible: true
для вивантаження:
- Встановіть
isCollectible
вtrue
, коли створюєте контекст, щоб дозволити вивантаження.
2. Моніторинг залежностей:
- Переконайтеся, що немає посилань на збірки в контексті, щоб забезпечити правильне вивантаження.
3. Обробка виключень:
- Обробляйте ситуації, коли не вдалося розв'язати збірку.
4. Уникати перевантаження стандартного контексту:
- Використовуйте користувацькі контексти для динамічного завантаження збірок, щоб уникнути забруднення стандартного контексту.
8. Обмеження
- Не можна вивантажити стандартний контекст:
- Лише користувацькі контексти підтримують вивантаження.
2. Вимагає уважного керування залежностями:
- Циклічні залежності або відсутні посилання можуть спричинити проблеми під час виконання.
3. Залежність від збору сміття:
- Вивантаження збірок пов'язане зі збором сміття, тому це не відбувається негайно.
9. Практичні сценарії для AssemblyLoadContext
- Системи плагінів:
- Динамічно завантажуйте плагіни та вивантажуйте їх, коли вони більше не потрібні.
2. Оновлення під час виконання:
- Динамічно завантажуйте оновлені збірки без перезапуску додатка.
3. Тестові середовища:
- Завантажуйте тестові збірки в ізоляції, щоб уникнути конфліктів.
4. Виконання скриптів:
- Виконуйте скрипти, надані користувачем, з ізольованими залежностями.
Перекладено з: AssemblyLoadContext in C#