在下面的代码示例中,Debug.Assert将失败。
如果从IBreaker注册中删除了AsImplementedInterfaces()扩展名,则foo.Bar将不为null。为什么会这样?
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> {}
}
答案 0 :(得分:9)
您的注册存在一些问题。首先,了解RegisterAssemblyTypes
的工作原理:它需要一个程序集并发现该程序集中的所有类,并向构建器注册类型。您可以使用AsXYZ
进一步扩充呼叫,以控制每个类型在最终容器中的键入方式。
现在,在您的示例中,每次注册所有类型时,您都会执行此操作三次,每次都有不同的扩充。您注册所有类型的前两个注册为特定接口的封闭类型。第三次,您再次注册相同的类型,但现在不作为封闭类型,有效地打破了之前的注册。
解决方案是使用Where
扩充来限制每次注册哪些类型的范围,以便相同类型不会使用不同的扩充注册多次。
答案 1 :(得分:0)
您的第三次注册调用没有任何过滤器,因此它将尝试重新注册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();