Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does AutoFac's AsImplementedInterfaces break my resolver on another type?

In the following code example, the Debug.Assert will fail.

If the AsImplementedInterfaces() extension is removed from the IBreaker registration, foo.Bar will not be null. Why is this the case?

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> {}
}
like image 765
brianc Avatar asked Dec 27 '22 01:12

brianc


1 Answers

There is a couple of issues with your registration. First off, understand how RegisterAssemblyTypes works: it takes an assembly and discovers all classes in that assembly and registers the types with your builder. You can further augment the call with AsXYZ to control how each type is keyed in the final container.

Now, in your sample you are doing this three times, each time with different augmentations, every time you will register all types. The first two registrations you are registering all types as closed types of a spesific interface. The third time, you are again registering the same types but now not as closed types, effectively breaking the previous registrations.

The solution is to use the Where augmentation to limit the scope of which types are registered each time, so that the same types are not registered several times with different augmentations.

like image 178
Peter Lillevold Avatar answered May 01 '23 10:05

Peter Lillevold