问题 是否可以从Autofac容器构建器中删除现有注册?


这些方面的东西:

builder.RegisterType<MyType>().As<IType>();
builder.RegisterType<MyType2>().As<IType>();
builder.DeRegisterType<MyType>().As<IType>()

var container = builder.Build();
var types = container.Resolve<IEnumerable<IType>>();
Assert.IsTrue(types.Count == 1);
Assert.IsTrue(types[0].GetType == typeof(MyType2));

场景:我经历了一堆程序集,当我去注册类型但我想 确保我只有一个给定类型的实现。我需要在创建容器之前执行此操作。我可以自己跟踪,但如果Autofac可以帮助我,那将会很好。


8883
2018-02-23 12:46


起源

我有另一个理由想要这个:使用RegisterAssemblyTypes我得到一个默认的'背景' InstancePerDependencyScope 决议。在此之后我想将其中一些升级到 InstancePerLifetimeScope。通过重新注册它们可以正常工作,直到我解决了一些可枚举的某个接口(例如,在多个类上实现的接口)。删除“后台”注册将允许这样做。 - Josh Gallagher
对于我发现的特定问题 RegisterAssemblyTypes().Except<TypeForUpgrading>() 和其他流畅的方法,可以控制注册的装配类型的选择和处理。 - Josh Gallagher


答案:


这不能直接使用 ContainerBuilder,除非你从一个新的重新开始。请注意,首先构建一个容器,您应该能够构建一个新的容器,过滤掉不需要的类型并重用第一个容器中的注册。喜欢这个:

...
var container = builder.Build();

builder = new ContainerBuilder();
var components = container.ComponentRegistry.Registrations
                    .Where(cr => cr.Activator.LimitType != typeof(LifetimeScope))
                    .Where(cr => cr.Activator.LimitType != typeof(MyType));
foreach (var c in components)
{
    builder.RegisterComponent(c);
}

foreach (var source in container.ComponentRegistry.Sources)
{
    cb.RegisterSource(source);
}

container = builder.Build();

这不是很优雅,但它的工作原理。现在,如果你可以详细说明 为什么 你想做到这一点,也许还有更好的方法。


12
2018-02-23 22:41



添加了Why部分 - Pawel Pabich
聪明的主意。您还需要复制RegistrationSources属性,但这可行。 - Nicholas Blumhardt
@Nicholas - 在那里,复制了消息来源。此外,不知道它有什么影响,但我最终得到了重复 LifetimeScope 零件。所以过滤掉那个。 - Peter Lillevold
@Nicholas Blumhardt,您能解释一下我们为什么需要它吗?注册/解决功能无需第二次预告即可运行 - monstr
这有错误吗? foreach行中的'c'是什么(c.ComponentRegistry.Sources中的var source) - Damien Sawyer


Peter L.可能是最直接的选择。

要彻底解决这个问题,您是否可以修改发现组件的方式,以便在注册之前对其进行过滤?似乎必须有一种方法可以解决这个问题......这也可能是一个挑战,以确定哪些组件要保留哪些组件以及要删除哪些组件。

更复杂的方法是覆盖 IEnumerable 支持过滤掉你不想要的东西。即复制并修改此代码以创建一个 FilteredCollectionSource 排除了你不想要的组件。

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService);

会成为:

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService)
    .Where(reg => /* not a duplicate */);

如果你添加你的 FilteredCollectionSource 使用的建设者 RegisterSource() 应该使用它而不是内置的。


1
2018-02-24 10:11



不幸的是,我批量生产组件,批次数量未知。感谢帮助 - Pawel Pabich