我有autofac注册的情况,其中服务彼此相关。这就是我现在所拥有的:
var builder = new ContainerBuilder();
const string A = "A";
const string B = "B";
//Part 1
builder.RegisterType<ClassA1>().Named<IClass1>(A);
builder.RegisterType<ClassA2>().Named<IClass2>(A);
builder.RegisterType<ClassB1>().Named<IClass1>(B);
builder.RegisterType<ClassB2>().Named<IClass2>(B);
//Part 2
builder.Register(c => new ClassProcess(A, c.ResolveNamed<IClass1>(A), c.ResolveNamed<IClass2>(A))).Named<ClassProcess>(A).SingleInstance();
builder.Register(c => new ClassProcess(B, c.ResolveNamed<IClass1>(B), c.ResolveNamed<IClass2>(B))).Named<ClassProcess>(B).SingleInstance();
//Part 3
builder.Register(c => new ClassProcessDependency(c.ResolveNamed<ClassProcess>(B), c.ResolveNamed<ClassProcess>(A)));
在第1部分中,我定义了成对连接的两个基本类,IClass1和IClass2。
在第2部分中,我定义了一个连接这两个类的“进程”。这个过程实际上传递给了程序的其余部分,它采用了IEnumerable。
在第3部分中,我定义了这些进程之间存在的任何依赖关系,以便它们以正确的顺序执行。
我在这里寻找的是Autofac中的一些注册方法,它可以使用先前使用name / key / meta注册的服务,并使用该数据注册新服务。
编辑:请注意,我正在尝试查找是否有任何特定于Autofac的方法来执行此操作。
答案 0 :(得分:3)
假设您在列表中有常量,可以通过...
进行枚举IEnumerable<string> constants
...有没有理由你不能这样做?
foreach(var constant in constants)
{
// Careful of the closure...
var loopItem = constant;
builder
.Register(c =>
new ClassProcess(
loopItem,
c.ResolveNamed<IClass1>(loopItem),
c.ResolveNamed<IClass2>(loopItem)))
.Named<ClassProcess>(loopItem)
.SingleInstance();
}
除非我误解或误解,否则唯一阻止你的是标识符常量集不在列表中,这不是Autofac可以帮助你的。
如果您不喜欢在代码中使用foreach,则可以将其隐藏在模块中:
public class ProcessModule : Autofac.Module
{
private IEnumerable<string> _constants;
public ProcessModule(IEnumerable<string> constants)
{
this._constants = constants;
}
protected override void Load(ContainerBuilder builder)
{
// Put the foreach here and loop over this._constants.
}
}
然后在主代码中注册模块:
builder.RegisterModule(new ProcessModule(constants));
如果你不能像那样循环,那么你的自动化方法可能会受到限制。或者,至少,你会看到更多的东西...... < EM>复杂
ContainerBuilder
并不真正允许在注册时直接访问注册项目集,因此您必须进行更多低级别的欺骗。您可以实现IRegistrationSource
来查找特定类型的所有命名注册并执行自动化。
不幸的是,如上所述,这个过程有点复杂,所以我不打算写出一个完整的解决方案。我会告诉你基本上我认为会起作用的,尽管,并为您提供一些参考,以查看源代码中的示例。
在开始这条道路之前,Nick Blumhardt has a nice article on his blog解释了如何编写其中一条,并使用其中一个内置的Autofac来源作为示例。
首先,您需要实现Autofac.Core.IRegistrationSource
。这是用于执行添加隐式集合支持的接口(因此,如果您注册了五个IFoo
实例你可以解决IEnumerable<IFoo>
并且它有效。您可以在核心Autofac程序集中查看Autofac代码中的注册源示例:
注册源中的主要功能是RegistrationsFor
方法,它返回源生成的注册列表:
IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor);
您对此方法的实施将检查传入的service
是否为......
Autofac.Core.KeyedService
(因为您正在命名所有服务)和如果所有行星都对齐,则会为IComponentRegistration
返回ClassProcess
并填写所有设置。
现在,这将变得更加困难,因为您的ClassProcess
需要两个已命名的输入参数,您可能不希望注册命名的ClassProcess
,除非您确定所有参数依赖项也已注册,因此您必须跟踪您看到的服务,并且只有在您看到它的所有依赖项后才会注册ClassProcess
。(您可以使用{ {1}}来确定服务的名称是什么。)
此外,您不再使用KeyedService
创建该组件注册,因此您必须在注册中找出与“生命周期范围”等内容相对应的所有正确设置,等等
获得ContainerBuilder
后,您需要将其与IRegistrationSource
联系起来。
ContainerBuilder
再次,如果您对此感兴趣,我会在Autofac树中查看这些源文件。由于复杂性,这不是许多人失败的道路。
老实说...... 如果你可以循环查看常数,我会这样做。为避免foreach循环,这似乎需要做很多工作。