【问题标题】:Why does AutoFac's AsImplementedInterfaces break my resolver on another type?为什么 AutoFac 的 AsImplementedInterfaces 会在另一种类型上破坏我的解析器?
【发布时间】:2012-05-03 22:22:34
【问题描述】:

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

如果从 IBreaker 注册中删除 AsImplementedInterfaces() 扩展,则 foo.Bar 不会为空。为什么会这样?

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> {}
}

【问题讨论】:

    标签: c# .net dependency-properties autofac


    【解决方案1】:

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

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

    解决的办法是使用Where扩充来限制每次注册的类型的范围,使得相同的类型不会被不同的扩充多次注册。

    【讨论】:

    • 啊,现在我明白了。感谢您的精彩解释。
    【解决方案2】:

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

    尝试像其他 2 个调用一样添加过滤器。

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

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

    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();
    

    【讨论】:

    • 您不能使用 .AsClosedTypesOf() 因为 IBreaker 不是通用的,因为 AsClosedTypesOf 仅用于通用注册。另外,我没有听从您对为什么会发生这种情况的解释。 IBreaker 和 BreakerImpl 与任何 [I]Foo 或 [I]Bar 接口或类型无关,因此据我所知,注册不应该有任何影响。
    猜你喜欢
    • 2021-10-20
    • 1970-01-01
    • 2013-02-28
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 2013-06-07
    相关资源
    最近更新 更多