C# 是否可以从Autofac容器生成器中删除现有注册?

C# 是否可以从Autofac容器生成器中删除现有注册?,c#,autofac,C#,Autofac,大致如下: builder.RegisterType<MyType>().As<IType>(); builder.RegisterType<MyType2>().As<IType>(); builder.DeRegisterType<MyType>().As<IType>() var container = builder.Build(); var types = container.Resolve<IEnumer

大致如下:

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));
builder.RegisterType().As();
builder.RegisterType().As();
builder.DeRegisterType().As()
var container=builder.Build();
var types=container.Resolve();
Assert.IsTrue(types.Count==1);
Assert.IsTrue(类型[0]。GetType==typeof(MyType2));
场景:我经历了一堆程序集,在进行时我注册了类型,但我想
确保给定类型只有一个实现。我需要在创建容器之前执行此操作。我可以自己跟踪,但如果Autofac能帮我一点忙,那就太好了。

这不能直接使用
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();

这几乎不是很优雅,但很有效。现在,如果你能详细说明你为什么要这样做,也许有更好的方法。

彼得·L.可能得到了最直接的选择

为了彻底解决这个问题,您能否修改发现组件的方式,以便在注册之前对其进行过滤?看来一定有办法解决这个问题。。。在今后的工作中,确定哪些组件需要保留,哪些组件需要删除,这可能也是一个挑战

一种更复杂的方法是覆盖
IEnumerable
支持,过滤掉您不想要的东西。也就是说,复制并修改此代码以创建一个
FilteredCollectionSource
,该代码不包含您不需要的组件

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService);
将成为:

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

如果您使用
RegisterSource()
将您的
FilteredCollectionSource
添加到构建器中,应该使用它,而不是内置的。

聪明的主意。您还需要跨多个站点复制RegistrationSources属性,但这会起作用。@Nicholas-在那里,添加了复制源。另外,我不确定它有什么影响,但我最终得到了
LifetimeScope
组件的副本。所以也要过滤掉这个。@Nicholas Blumhardt,你能解释一下我们为什么需要它吗?注册/解析功能在没有第二个foreachi的情况下可以正常工作这里面有bug吗?foreach行中的'c'是什么(c.ComponentRegistry.Sources中的var source)@NicholasBlumhardt我遇到了这个问题,想找到一个解决我在decorators中遇到的问题的方法(请参阅:)。更换注册可能不是解决办法,但在这种情况下,这样做会很方便。在我的例子中,更好的解决方案是,如果装饰注册覆盖了现有的注册,就像其他组件一样。不幸的是,我分批得到组件,分批的数量未知。感谢您的帮助我有另一个想要这样做的原因:使用RegisterAssemblyTypes,我会得到默认的“背景”分辨率
InstancePerDependencyScope
。在此之后,我想将其中一些升级到
InstancePerLifetimeScope
。通过重新注册它们,直到我解析某个接口的可枚举项(例如,在多个类上实现的接口)为止,这样做效果很好。删除“后台”注册将允许这样做。对于我的特定问题,我发现了
RegisterAssemblyTypes().Exception()
和其他可以控制正在注册的程序集类型的选择和处理的fluent方法。