4

次のコード例では、Debug.Assert は失敗します。

AsImplementedInterfaces() 拡張機能が IBreaker 登録から削除された場合、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> {}
}
4

2 に答える 2

10

登録にはいくつかの問題があります。まず、どのようにRegisterAssemblyTypes機能するかを理解します。アセンブリを取得し、そのアセンブリ内のすべてのクラスを検出し、型をビルダーに登録します。呼び出しをさらに拡張して、AsXYZ各タイプが最終的なコンテナーでどのようにキー設定されるかを制御できます。

さて、あなたのサンプルでは、​​これを 3 回行っています。毎回異なる拡張を使用して、毎回すべてのタイプを登録します。最初の 2 つの登録では、すべての型を特定のインターフェイスの閉じた型として登録しています。3 回目は、同じ型を再度登録しますが、閉じた型としてではなく、以前の登録を実質的に破ります。

解決策は、オーグメンテーションを使用して、Where毎回登録されるタイプのスコープを制限し、同じタイプが異なるオーグメンテーションで何度も登録されないようにすることです。

于 2012-05-04T06:14:51.787 に答える
0

3 番目の登録呼び出しにはフィルターがないため、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();
于 2012-05-03T22:57:19.730 に答える