如何使用 Autofac 注册开放泛型接口的所有实现



我目前有一个用于管道中单个步骤的接口。

public interface IPipelineStep<T1, T2>
where T1: ModelObject
where T2: EntityObject { }

我有一大堆实现此接口的步骤:

public class ValidateModelStep<T1, T2> : IPipelineStep<T1, T2>
where T1: ModelObject
where T2: EntityObject { }
public class Step2<T1, T2> : IPipelineStep<T1, T2>
where T1: ModelObject
where T2: EntityObject { }
public class Step3<T1, T2> : IPipelineStep<T1, T2>
where T1: ModelObject
where T2: EntityObject { }
public class Step4<T1, T2> : IPipelineStep<T1, T2>
where T1: ModelObject
where T2: EntityObject { }

我目前正在像这样注册它们:

builder.RegisterGeneric(typeof(ValidateModelStep<,>)).As(typeof(IPipelineStep<,>)).AsSelf();
builder.RegisterGeneric(typeof(Step2<,>)).As(typeof(IPipelineStep<,>)).AsSelf();
builder.RegisterGeneric(typeof(Step3<,>)).As(typeof(IPipelineStep<,>)).AsSelf();
builder.RegisterGeneric(typeof(Step4<,>)).As(typeof(IPipelineStep<,>)).AsSelf();

然后我可以使用 autofac 来实例化这些步骤。问题是,我有很多很多步骤。每次我创建一个新文件时都必须注册每一个,这非常令人沮丧。

有没有办法一次注册它们?

我知道您可以使用程序集扫描和AsClosedTypesOf,但这似乎不适用于开放泛型接口的开放泛型实现。

我尝试过的事情:

builder.RegisterAssemblyTypes(myAssembly).AsClosedTypesOf(typeof(IPipelineStep<,>)).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(myAssembly).AssignableTo(typeof(IPipelineStep<,>)).As(typeof(IPipelineStep<,>)).AsSelf();
builder.RegisterAssemblyTypes(myAssembly)
.Where(t => t.IsAssignableFrom(typeof(IPipelineStep<,>)))
.As(typeof(IPipelineStep<,>)).AsSelf();

当接口的实现也必须包含泛型时,有什么方法可以使用AsClosedTypesOf

提前致谢

我想最直接的方法是自己扫描程序集:

foreach (var t in myAssembly.GetTypes()
.Where(c => !c.IsInterface && c.IsGenericTypeDefinition && c.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IPipelineStep<,>)))) {
builder.RegisterGeneric(t).As(typeof(IPipelineStep<,>)).AsSelf();
}

这基本上过滤了开放泛型的类型并实现IPipelineStep<>,然后在容器中寄存器。我想如果你愿意,你可以用RegisterAssemblyTypes.Where(...)做类似的事情。

原始帖子的评论可能是公认的答案,因为这非常适合类似的用例。

我想注册我的INotificationHandler<>接口的所有实现。 使用 Autofac 的程序集注册,我能够完成此操作。

builder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(INotificationHandler<>))
.InstancePerDependency()
.PreserveExistingDefaults();

通过使用PreserveExistingDefaults每个项目都被添加到IEnumerable<INotificationHandler<T>>并且可以解析为一个大块或独立解决

using var scope = container.BeginLifetimeScope();
var handlers = scope
.Resolve<IEnumerable<INotificationHandler<T>>>()
.Select(h => h.HandleNotification(notification, cancellationToken));

上面的代码解析具有相同泛型类型参数的所有实例。 具体实现和注册的第一个接口都可以并且将会得到解决。

相关内容

  • 没有找到相关文章

最新更新