我想基于T为我的Open Generic ICommandHandler创建一个keyedService。当ICommandHandler有一个继承自ConsultantCommand的T时,我想注册一个ConsultatCommandHanlder键控服务
知道怎么做吗?或者如果有可能的话?我是AutoFac的新手并且正在努力。
我目前正在注册CommandHandler:
//Register All Command Handlers
builder.RegisterAssemblyTypes(assemblies)
.As(
t =>
t.GetInterfaces()
.Where(a => a.IsClosedTypeOf(typeof (ICommandHandler<>)))
.Select(a => new KeyedService("commandHandler", a))).InstancePerHttpRequest();
如果可能,我猜我必须在获得Closed Type时识别CommandHandler,并以某种方式识别Command实现ConsultantCommand的那些。
我试过了:
builder.RegisterAssemblyTypes(assemblies)
.As(
t =>
t.GetInterfaces()
.Where(a => a.IsClosedTypeOf(typeof(ICommandHandler<>)) &&
a.GetGenericArguments()[0].IsSubclassOf(typeof(ConsultantCommand)))
.Select(a => new KeyedService("ConsultantCommandHandler", a))).InstancePerHttpRequest();
但是,快乐似乎并不起作用。它编译但现在没有注册CommandHandler甚至那些从ConsultantCommand继承的命令。我认为我的语法都错了
答案 0 :(得分:1)
你想:
builder.RegisterAssemblyTypes(assemblies)
.AsClosedTypesOf(typeof(ICommandHandler<>))
.AsSelf()
.AsImplementedInterfaces()
.InstancePerHttpRequest();
答案 1 :(得分:1)
首先,您需要确保宣布您的ICommandHandler<T>
支持协方差:
public interface ICommandHandler<out T> { }
out
很重要,否则您将无法立即解决所有ConsultantCommand
个处理程序。您还将获得Autofac例外。
接下来,使用Named
扩展方法注册您的命名服务,而不是自己动手。语法如下所示:
builder.RegisterAssemblyTypes(assemblies)
.Where(t =>
t.IsClosedTypeOf(typeof(ICommandHandler<>)) &&
t.GetInterfaces()[0]
.GetGenericArguments()[0]
.IsAssignableTo<ConsultantCommand>())
.Named("name", typeof(ICommandHandler<ConsultantCommand>))
.InstancePerHttpRequest();
它将ICommandHandler<T>
T
从[{1}}派生的所有服务ConsultantCommand
注册为ICommandHandler<ConsultantCommand>
。您必须使用基本类型,或者,您将无法一次解析所有处理程序。没有任何方法可以“解析从此基本类型派生的所有服务”。也无法解决开放式泛型列表。
解决处理程序列表后,您需要解析名为IEnumerable<T>
的内容:
using(var scope = container.BeginLifetimeScope())
{
var x =
scope.ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");
}
当然,您正在使用InstancePerHttpRequest
,所以它更像是:
var x =
AutofacDependencyResolver
.Current
.RequestLifetimeScope
.ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");
如上所述,您必须注册为封闭式通用,因为这不起作用:
// WON'T WORK:
scope.ResolveNamed<IEnumerable<ICommandHandler<>>>("name");
您可以根据需要修改注册。其余的注册扩展应该照常工作 - 如果你想将事情注册为已实现的接口或其他任何东西,它应该与RegisterAssemblyTypes
一起工作,就像你使用单个服务一样。