如何在Autofac注册中调用异步方法?

Bea*_*ker 11 .net c# asynchronous factory autofac

我想awaitable async在注册过程中调用一个方法,如下所示:

// builder variable contains Autofac ContainerBuilder
builder.Register(
    (async (context, parameters) => // need async here
        {
            var someClass = new SomeClass(context.Resolve<ISomeDependency>());
            await someClass.SomeAsyncInitMethod(); // need to await result
            return someClass;
        })).As<ISomeClass>().SingleInstance();
Run Code Online (Sandbox Code Playgroud)

SomeClass实现ISomeClass为服务.重要的部分是someClass.SomeAsyncInitMethod()电话.这是async因为,因此我需要在await这里将async关键字放入Register方法中.但现在Autofac认为这会返回一个Task<SomeClass>不可注册的Service ISomeClass.

如何实现上述注册SomeClassISomeClass等待时async的init方法?

Vet*_*ras 7

这是一个老问题,但我认为 autofac 不支持这一点。

我们用了:

builder.Register(c =>
  {
      var bar= c.Resolve<IBar>();
      var foo = new Foo(bar);
      return foo.ComputeAsync().ConfigureAwait(false).GetAwaiter().GetResult();
  })
.As<IFoo>()
.SingleInstance();
Run Code Online (Sandbox Code Playgroud)

但正如评论中提到的:在 Autofac 中注册异步工厂


ast*_*tef 5

我认为在解析阶段进行任何 I/O 密集型工作都是错误的设计,因为完全控制此操作的顺序、捕获异常、重复它们、控制其中一些之间的时间等通常很重要。

解决方案是与工厂一起推迟它们。让我换SomeClass一个更有意义的NpgsqlConnection

var builder = new ContainerBuilder();
builder.Register(context =>
{
    // make sure not to capture temporary context:
    // https://autofaccn.readthedocs.io/en/latest/advanced/concurrency.html#service-resolution
    var connectionString = context.Resolve<IConfiguration>().GetConnectionString("MyDb");

    return new Func<Task<NpgsqlConnection>>(async () =>
    {
        var connection = new NpgsqlConnection(connectionString);
        await connection.OpenAsync();
        return connection;
    });
});
Run Code Online (Sandbox Code Playgroud)

以下是连接用户的样子:

public sealed class Repository
{
    private readonly Func<Task<NpgsqlConnection>> _connectionFactory;

    public Repository(Func<Task<NpgsqlConnection>> connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }

    public async Task<string> GetServerVersionAsync()
    {
        using (var openedConnection = await _connectionFactory())
            return openedConnection.ServerVersion;
    }
}
Run Code Online (Sandbox Code Playgroud)

即使 Autofac 支持异步注册,在Repository构造函数中要求工厂仍然是有益的,因为连接是一种有限的资源,最好限制它打开的时间。