支持异步Get和异步实例创建的IoC容器

时间:2014-05-17 16:43:01

标签: .net inversion-of-control async-await ioc-container

我最近开始使用ASP.NET和DynamoDB在C#中编写大量的异步/等待代码。我已经选择并设置Ninject作为我的IoC容器。从我在Ninject文档中找到并在线搜索,Ninject没有特定的异步支持。这是有道理的,因为它是在将async / await添加到C#之前编写的。但是,an article on MSDN关于异步编程中的最佳实践建议一直使用&#34; Async&#34;做法。是否有支持异步解析和注册异步工厂的.NET IoC容器?即如果它在Ninject中受支持,类似于kernel.GetAsync<IMyService>()返回Task<IMyService>kernel.Bind<IMyService>().ToMethod(ctx => factory.CreateAsync())之类的注册方法,其中CreateAsync方法返回Task<MyService>

示例/为何需要

我的ASP.NET异步代码实际上有一个死锁,因为我被迫阻止异步代码(要理解为什么会发生这种情况,请参阅Don't Block on Async Code)。我使用.ConfigureAwait(false)解决了这个问题,但建议两者都做以防止出现问题。此外,我被迫在一个地方添加ConfigureAwait(false),在那里我无法证明我不需要上下文,因为我正在调用一个可能在将来使用上下文的委托。

我有一个异步的用户存储库,因为它访问我的数据存储。

public interface IUserRepository
{
    Task<User> GetAsync(Guid id);
}

我将当前用户注册为依赖项,因此我可以访问姓名,电子邮件等信息并进行安全检查。

kernel.Bind<User>().ToMethod(GetCurrentUser).InRequestScope();

// The implementation of GetCurrentUser
public static User GetCurrentUser(IContext context)
{
    var repository = context.Kernel.Get<IUserRepository>();
    var currentUserId = /* get current user id here from HttpContext.Current */;
    return repository.GetAsync(currentUserId).Result; // blocks until the user is loaded 
}

此代码在.Result上陷入僵局。我真正需要的是能够从Task<User>返回GetCurrentUser并让Ninject使用异步代码正确处理它。

3 个答案:

答案 0 :(得分:4)

据我所知,没有支持async的IoC容器。我认为更好的IoC和对async的嘲弄支持是async世界统治计划中的下一个合乎逻辑的步骤。

如果您的用户存储库可以同步创建,那么您当然可以直接使用它:

var user = await context.Kernel.Get<IUserRepository>().GetAsync(currentUserId);

但是,任何异步都必须在IoC容器“外部”完成。我在async constructors上发布了一篇博文,并在async services上发表了MSDN文章,展示了今天处理这些情况的最佳方法。希望在不久的将来,这将在真正的IoC async支持下发生变化。

答案 1 :(得分:0)

您可以使用支持异步依赖注入的我的库AsyncContainer

注册异步工厂

public static async Task<EmailService> EmailServiceFactory() 
{
  await Task.Delay(1000);
  return new EmailService();
}

//...
var container = new Container();

container.Register<IDatabase, Database>();
container.Register<IEmailService>(EmailServiceFactory);

异步解决实例:

var instance = await container.GetInstanceAsync<NotificationService>();

答案 2 :(得分:0)

我正在使用支持异步解析的源生成器来编译IOC容器。

https://github.com/YairHalberstadt/stronginject尝试一下。