Autofac.如何在构造函数中注入打开的泛型委托

本文关键字:泛型 注入 构造函数 Autofac | 更新日期: 2023-09-27 17:51:11

我试图通过像这样的构造函数注入一个开放泛型的委托

protected AQuery(Func<string, IQuery<T>> getQuery)
{
    query = getQuery("contextName");
}

和Register类似

builder
   .Register<Func<string, IQuery<T>>>(
       c => ctx => 
       new Query(c.ResolveNamed<IDbContext>(ctx)));

我找不到任何API帮助文档。

我可以在不涉及泛型的地方使用类似的注册

Autofac.如何在构造函数中注入打开的泛型委托

你试图实现的似乎是一种非常实用的方法,在f#等函数式语言中工作得很好,但是。net的大多数DI容器都是为面向对象语言构建的,它们本质上是面向类型的,而不是面向委托或面向函数的。你想做的,不能很容易地完成Autofac,或任何其他DI容器。

即使Autofac能够将泛型方法映射到Func委托,你仍然需要相当数量的反射来注册它。例如这个假设的RegisterGenericFunc方法:

builder.RegisterGenericFunc(
    typeof(Func<,>).MakeGenericType(typeof(string), typeof(IQuery<>)),
    typeof(Bootstrapper).GetMethod("QueryFuncFactory"));
public static Func<string, IQuery<T>> QueryFuncFactory<T>(IComponentContext c) {
    return ctx => new Query(c.ResolveNamed<IDbContext>(ctx)));
}

要实现这一点,Autofac不仅要能够处理委托,还要能够理解部分开放泛型类型(您的Func<string, IQuery<T>>是部分开放泛型)。

因此,与其这样做,您可能想要退回到更面向对象的方法,并定义一个清晰的接口来描述您的抽象:

public interface IQueryFactory<T> {
     IQuery<T> CreateQuery(string context);
}

你的实现可以像这样:

public class AutofacQueryFactory<T> : IQueryFactory<T> {
     private readonly IComponentContext c;
     public AutofacQueryFactory(IComponentContext c) {
         this.c= c;
     }
     public IQuery<T> CreateQuery(string context) {
         return new Query<T>(c.ResolveNamed<IDbContext>(context));
     }
}

接口实现对的注册方式如下:

build.RegisterGeneric(typeof(AutofacQueryFactory<>)).As(typeof(IQueryFactory<>);

你的消费者可以依靠IQueryFactory<T>:

protected AQuery(IQueryFactory<T> getQuery)
{
    query = getQuery.CreateQuery("contextName");
}