我正在尝试通过像这样的构造函数注入一个开放泛型的委托
protected AQuery(Func<string, IQuery<T>> getQuery)
{
query = getQuery("contextName");
}
并注册类似
的内容builder
.Register<Func<string, IQuery<T>>>(
c => ctx =>
new Query(c.ResolveNamed<IDbContext>(ctx)));
我找不到任何这样的API帮助文档。
我可以使用类似的注册,但不涉及泛型。
答案 0 :(得分:9)
您尝试实现的功能似乎是一种非常实用的方法,在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");
}