为什么AutoFac的AsImplementInterfaces会破坏我在另一种类型的解析器

本文关键字:类型 另一种 AsImplementInterfaces AutoFac 为什么 | 更新日期: 2023-09-27 18:33:02

在下面的代码示例中,Debug.Assert 将失败。

如果 AsImplementInterfaces() 扩展从 IBreaker 注册中删除,foo。条形图不会为空。为什么会这样呢?

using System;
using System.Diagnostics;
using System.Reflection;
using Autofac;
namespace AutoFacTest
{
class Program
{
    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        var thisAssembly = Assembly.GetExecutingAssembly();
        builder.RegisterAssemblyTypes(typeof(IFoo<>).Assembly, thisAssembly).AsClosedTypesOf(typeof(IFoo<>))
                .AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency();
        builder.RegisterAssemblyTypes(typeof(IBar<>).Assembly, thisAssembly)
               .AsClosedTypesOf(typeof(IBar<>)).AsImplementedInterfaces().InstancePerDependency();
        builder.RegisterAssemblyTypes(typeof(IBreaker).Assembly, thisAssembly).InstancePerDependency()
                .AsImplementedInterfaces(); //<------ will work if this is removed
        var container = builder.Build();
        var foo = container.Resolve<IFoo<int>>();
        Debug.Assert(foo.Bar!=null);
        Console.ReadLine();
    }
}
public interface IBreaker {}
public class BreakerImpl<T> : IBreaker {}
public class BarImpl : IBar<int>{}
public class FooImpl : IFoo<int>
{
    public IBar<int> Bar { get; set; }
}
public interface IFoo<T>
{
    IBar<T> Bar { get; set; }
}
public abstract class Foo<T> : IFoo<T>
{
    public IBar<T> Bar { get; set; }
}
public interface IBar<T>{}
public abstract class Bar<T> : IBar<T> {}
}

为什么AutoFac的AsImplementInterfaces会破坏我在另一种类型的解析器

您的注册存在一些问题。首先,了解RegisterAssemblyTypes的工作原理:它采用程序集并发现该程序集中的所有类,并向构建器注册类型。可以使用 AsXYZ 进一步扩充调用,以控制每种类型在最终容器中的键控方式。

现在,在您的示例中,您将执行此操作三次,每次使用不同的增强,每次您将注册所有类型。前两个注册是将所有类型注册为特殊接口的封闭类型。第三次,您再次注册相同的类型,但现在不是封闭类型,有效地打破了以前的注册。

解决方案是使用Where扩充来限制每次注册的类型范围,以便相同的类型不会使用不同的扩充多次注册。

你的第三个寄存器调用没有任何过滤器,所以它会尝试重新注册IFoo和IBar的所有具体实现。当你省略AsImplmentedInterfaces()时,它只会将具体类注册为它们自己的类型。

尝试添加过滤器,就像您处理其他 2 个调用一样。

builder.RegisterAssemblyTypes(typeof(IBreaker).Assembly, thisAssembly)
            .InstancePerDependency()
            .AsClosedTypesOf<IBreaker>()
            .AsImplementedInterfaces();

如果您希望注册所有剩余的课程,请尝试为您已注册的课程添加 Except 调用。

builder.RegisterAssemblyTypes(typeof(IBreaker).Assembly, thisAssembly)
            .InstancePerDependency()
            .Except<IFoo>().Except<IBar>() //Not sure if you have to specify the concrete types or if the interfaces are fine
            .AsImplementedInterfaces();
相关文章: