hus*_*ler 3 c# generics dependency-injection autofac
我试图通过像这样的构造函数注入一个开放泛型的委托
protected AQuery(Func<string, IQuery<T>> getQuery)
{
query = getQuery("contextName");
}
Run Code Online (Sandbox Code Playgroud)
并注册类似的东西
builder
.Register<Func<string, IQuery<T>>>(
c => ctx =>
new Query(c.ResolveNamed<IDbContext>(ctx)));
Run Code Online (Sandbox Code Playgroud)
我找不到任何这样的API帮助文档.
我能够使用类似的注册,其中不涉及泛型.
Ste*_*ven 10
您正在尝试实现的功能似乎是一种非常实用的方法,在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)));
}
Run Code Online (Sandbox Code Playgroud)
为了使其工作,Autofac不仅必须能够与代理一起工作,而且还能够理解部分开放泛型类型(您Func<string, IQuery<T>>的部分开放式通用).
因此,您可能希望回到更面向对象的方法,并定义一个描述您的抽象的清晰界面,而不是这样做:
public interface IQueryFactory<T> {
IQuery<T> CreateQuery(string context);
}
Run Code Online (Sandbox Code Playgroud)
您的实现可能如下所示:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
此接口实现对可以注册如下:
build.RegisterGeneric(typeof(AutofacQueryFactory<>)).As(typeof(IQueryFactory<>);
Run Code Online (Sandbox Code Playgroud)
您的消费者可以依赖IQueryFactory<T>:
protected AQuery(IQueryFactory<T> getQuery)
{
query = getQuery.CreateQuery("contextName");
}
Run Code Online (Sandbox Code Playgroud)