Как инициализировать объект, используя шаблон async-await
я пытаюсь следовать шаблону RAII в моих классах обслуживания, что означает, что когда объект создается, он полностью инициализируется. Однако я'Я сталкиваюсь с трудностями с асинхронными API. Структура рассматриваемого класса выглядит следующим образом:
class ServiceProvider : IServiceProvider // Is only used through this interface
{
public int ImportantValue { get; set; }
public event EventHandler ImportantValueUpdated;
public ServiceProvider(IDependency1 dep1, IDependency2 dep2)
{
// IDependency1 provide an input value to calculate ImportantValue
// IDependency2 provide an async algorithm to calculate ImportantValue
}
}
м также нацелена на избавление от побочных эффектов вImportantValue
getter, чтобы сделать его потокобезопасным.
Сейчас пользователиServiceProvider
создаст его экземпляр, подпишется на событиеImportantValue
изменить и получить начальныйImportantValue
, И тут возникает проблема с начальным значением. ПосколькуImportantValue
вычисляется асинхронно, класс не может быть полностью инициализирован в конструкторе. Вполне возможно, что изначально это значение будет равно нулю, но тогда мне нужно найти место, где оно будет вычислено в первый раз. Естественным местом для этого может бытьImportantValue
получатель, но яm таргетинг, чтобы сделать его потокобезопасным и без побочных эффектов.
Так что я'Я в основном застрял с этими противоречиями. Не могли бы вы помочь мне и предложить альтернативу? Инициализация значения в конструкторе, в то время как nice не является действительно необходимой, но никакие побочные эффекты и потокобезопасность свойства не являются обязательными.
Заранее спасибо.
РЕДАКТИРОВАТЬ: Еще одна вещь, чтобы добавить. Я'Я использую Ninject для создания экземпляров, и, насколько я понимаю, это не• Поддержка асинхронных методов для создания привязки. Хотя подход с инициированием какой-либо операции на основе задач в конструкторе будет работать, я не могу дождаться ее результата.
То есть два следующих подхода (предложенные в качестве ответов) не скомпилируются, поскольку возвращается Task, а не мой объект:
Kernel.Bind().ToMethod(async ctx => await ServiceProvider.CreateAsync())
или же
Kernel.Bind().ToMethod(async ctx =>
{
var sp = new ServiceProvider();
await sp.InitializeAsync();
})
Простое связывание будет работать, но яя не ожидаю результата асинхронной инициализации, запущенной в конструкторе, как предложил Стивен Клири:
Kernel.Bind().To();
... и этоне выглядит хорошо для меня.