Autofac:注册异步工厂方法

Rub*_*ink 5 c# asynchronous dependency-injection factory-method autofac

TL;DR:Autofac 支持类似 AutoFixture 的fixture.Get()机制吗?

我正在使用 Autofac 并且需要调用异步工厂方法,如下所示:

class AppModel
{
     public static async Task<AppModel> CreateAsync(IDependency x, IDependency2 y)
     { ... }
}
Run Code Online (Sandbox Code Playgroud)

对我来说执行此类方法并由 Autofac 提供参数的最简单方法是什么?即,我希望能够做类似的事情:

Task<AppModel> creationTask = <some autofaccery>(AppModel.CreateAsync);
var appModel = await creationTask();
Run Code Online (Sandbox Code Playgroud)

其中<some autofaccery>表示与ContainerBuilder和/或IContainer和/或某种形式的生成的委托或类似的交互的某种机制,它本质上是简洁的,并且使我无法显式指定工厂方法的参数。即,我想避免像 atm 那样显式解析每个参数 [和/或必须在依赖项发生变化时更新它们]:

var appModel = await AppModel.CreateAsync( 
    container.Resolve<IDependency>(),
    container.Resolve<IDependency2>());
Run Code Online (Sandbox Code Playgroud)

我位于基础设施组件领域,靠近组合根,可能会以编程方式定义组件注册和/或执行其他应限制在此处的肮脏操作。我不介意参与反射,因为它只被调用一次。

关键是我确实需要观察Exception所产生的任何结果Task

Task<T>在很大程度上是一个转移注意力的话题,但重点是,遵循定义同步工厂方法并让 Autofac 完成工作的正常模式不会成功(至少不会直接),即我不能只是改变它到:

     public static AppModel CreateAsync(IDependency x, IDependency2 y)
     { ... }
Run Code Online (Sandbox Code Playgroud)

我还想避免两阶段初始化 - 在初始化之前我不需要对象可用。

Rub*_*ink 0

(受到我在顶部添加的 TL;DR 的启发)

你可以实施一个ResolveAsync一系列方法:-

public static Task<T> ResolveAsync<T1, T>(Func<T1, Task<T>> func)
{
    return func(_container.Resolve<T1>());
}

public static Task<T> ResolveAsync<T1, T2, T>(Func<T1, T2, Task<T>> func)
{
    return func(_container.Resolve<T1>(), _container.Resolve<T2>());
}

public static Task<T> ResolveAsync<T1, T2, T3, T>(Func<T1, T2, T3, Task<T>> func)
{
    return func(_container.Resolve<T1>(), _container.Resolve<T2>(), _container.Resolve<T3>());
}
Run Code Online (Sandbox Code Playgroud)

这允许我做:

var appModel = await ResolveAsync<IDependency,IDependency2>(AppModel.CreateAsync);
Run Code Online (Sandbox Code Playgroud)

或者显然这些可以变成扩展方法:-

var appModel = await container.ResolveAsync<IDependency,IDependency2>(AppModel.CreateAsync);
Run Code Online (Sandbox Code Playgroud)

正在开发一个包装器以允许使用 C# 的原始类型推断:(我将节省精力,不再花费更多时间在不是为这项工作构建的语言/异步范式中实现正确的解决方案。