Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1345. #ЗаметкиНаПолях #AsyncTips Асинхронное Создание Объектов: Паттерн Асинхронной Инициализации Задача Вам нужен тип, требующий выполнения некоторой асинхронной работы в конструкторе, но вы не можете воспользоваться паттерном асинхронной фабрики, так как экземпляр создаётся с применением рефлексии (например, IoC-контейнера, связывания данных, Activator.CreateInstance и т. д.). Решение В таком сценарии вам приходится возвращать неинициализированный экземпляр, хотя ситуацию можно частично сгладить применением распространённого паттерна асинхронной инициализации. Каждый тип, требующий асинхронной инициализации, должен определять специальное свойство (обычно в интерфейсе-маркере):
public interface IAsyncInit
{
  Task Initialization { get; }
}

При реализации этого паттерна следует начать инициализацию, задав значение свойства Initialization в конструкторе. Доступ к результатам асинхронной инициализации (вместе с любыми исключениями) предоставляется через свойство Initialization. Пример реализации:
class MyType : IAsyncInit
{
  public MyType()
  {
    Initialization = InitAsync();
  }

  public Task Initialization 
   { get; private set; }
  
  private async Task InitAsync()
  {
    // асинхронно инициализируем экземпляр
    await Task.Delay(TimeSpan.FromSeconds(1));
  }
}

Экземпляр этого типа может быть создан и инициализирован примерно так:
var instance = DIContainer.Resolve<MyType>();
var asyncInit = instance as IAsyncInit;
if (asyncInit != null)
  await asyncInit.Initialization;

По возможности рекомендуется применять асинхронные фабрики или ленивую инициализацию вместо этого решения. Эти решения предпочтительны, потому что в них исключается доступ к неинициализированному экземпляру. Если ваши экземпляры создаются библиотеками внедрения зависимостей/инверсии управления, связывания данных и т. д., и вы вынуждены открыть доступ к неинициализированному экземпляру, придётся использовать паттерн асинхронной инициализации. Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.