Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自动传真机。如何在构造函数中插入打开的泛型委托_C#_Generics_Dependency Injection_Autofac - Fatal编程技术网

C# 自动传真机。如何在构造函数中插入打开的泛型委托

C# 自动传真机。如何在构造函数中插入打开的泛型委托,c#,generics,dependency-injection,autofac,C#,Generics,Dependency Injection,Autofac,我正试图通过这样的构造函数注入一个带有opengeneric的委托 protected AQuery(Func<string, IQuery<T>> getQuery) { query = getQuery("contextName"); } 受保护的查询(Func getQuery) { query=getQuery(“contextName”); } 然后注册类似 builder .Register<Func<string, IQuery

我正试图通过这样的构造函数注入一个带有opengeneric的委托

protected AQuery(Func<string, IQuery<T>> getQuery)
{
    query = getQuery("contextName");
}
受保护的查询(Func getQuery)
{
query=getQuery(“contextName”);
}
然后注册类似

builder
   .Register<Func<string, IQuery<T>>>(
       c => ctx => 
       new Query(c.ResolveNamed<IDbContext>(ctx)));
builder
.登记(
c=>ctx=>
新查询(c.ResolveNamed(ctx));
我找不到类似这样的API帮助文档


我能够在不涉及泛型的情况下使用类似的注册。

您试图实现的似乎是一种非常实用的方法,在函数式语言(如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)));
}
builder.RegisterGenericFunc(
typeof(Func).MakeGenericType(typeof(string),typeof(IQuery)),
typeof(Bootstrapper).GetMethod(“QueryFuncFactory”);
公共静态函数QueryFuncFactory(IComponentContext c){
返回ctx=>newquery(c.ResolveNamed(ctx));
}
但是,要使其起作用,Autofac不仅必须能够处理委托,还必须能够理解部分打开的泛型类型(您的
Func
是部分打开的泛型)

因此,与此相反,您可能希望退回到更面向对象的方法,并定义一个清晰的接口来描述您的抽象:

public interface IQueryFactory<T> {
     IQuery<T> CreateQuery(string context);
}
公共接口工厂{
IQuery CreateQuery(字符串上下文);
}
您的实现可以如下所示:

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));
     }
}
公共类AutofacQueryFactory:IQueryFactory{
私有只读IComponentContext c;
公共AutofacQueryFactory(IComponentContext c){
这个.c=c;
}
公共IQuery CreateQuery(字符串上下文){
返回新查询(c.ResolveNamed(context));
}
}
此接口实现对可以按如下方式注册:

build.RegisterGeneric(typeof(AutofacQueryFactory<>)).As(typeof(IQueryFactory<>);
build.RegisterGeneric(typeof(AutofacQueryFactory)).As(typeof(IQueryFactory);
您的消费者可以依赖于
IQueryFactory

受保护的队列(IQueryFactory getQuery)
{
query=getQuery.CreateQuery(“contextName”);
}

谢谢Steven。我实际上是在与确认了autofac的可能性后使用这种方法的。答案很旧,但仍在搜索引擎“autofac+委派”的榜首,因此认为为了完整起见,我应该添加更多关于这方面的信息。至少当前版本的AutoFac支持,这为这个问题提供了开箱即用的支持。
protected AQuery(IQueryFactory<T> getQuery)
{
    query = getQuery.CreateQuery("contextName");
}