Autofac 6.2 не разрешает (больше не разрешает) класс с закрытым конструктором?

#c# #inversion-of-control #autofac

Вопрос:

У меня есть этот код, который раньше работал в Autofac 2.6, но теперь больше не работает в 6.2 ( последняя версия):

 class Program
{
    static void Main(string[] args)
    {
        Holder holder = null;

        Build(c =>
        {

            holder = new Holder() { Verifiers = c.Resolve<Verifiers>() };
        });
        var res = holder.Verifiers;
        Console.WriteLine("Success");
    }


    private static void Build(Action<IContainer> container)
    {
        var builder = new ContainerBuilder();
        builder.RegisterAssemblyTypes(typeof(Verifiers).Assembly).AsSelf().AsImplementedInterfaces();
        container(builder.Build());
    }
}

public class PrivateConstructorClass
{
    public static PrivateConstructorClass Create()
    {
        return new PrivateConstructorClass();
    }
    private PrivateConstructorClass() //this is the problem
    {

    }
}


public class Verifiers
{

}

public class Holder
{
    public Verifiers Verifiers { get; set; }
}
 

Из — за этой ошибки:

Автофак.Ядро.Активаторы.Отражение.NoConstructorsFoundException
HResult=0x80131500 Сообщение=Не найдено доступных конструкторов для типа ‘AutofacTest46PrivateConstructor.Частный строительный класс».
Источник=Трассировка стека Autofac: в Autofac.Core.Активаторы.Отражение.DefaultConstructorFinder.GetDefaultPublicConstructors(Тип типа) в Autofac.Core.Активаторы.Отражение.DefaultConstructorFinder.Найдите конструкторы(Тип TargetType) в Autofac.Core.Активаторы.Отражение.Активатор отражения.Сконфигурируйте Pipeline(IComponentRegistryServices, компонентные службы регистрации, конвейерный конструктор решений для сборки)
в Autofac.Ядро.Регистрация.Регистрация компонентов.BuildResolvePipeline(IComponentRegistryServices, регистрационные службы, конвейерная сборка IResolvePipelineBuilder) в Autofac.Core.Registration.Регистрация компонентов.BuildResolvePipeline(IComponentRegistryServices услуги регистрации) в Autofac.Core.Регистрация.Конструктор компонентов.Сборка() в Autofac.Сборщик контейнеров.Сборка(параметры компоновки контейнеров) в AutofacTest46PrivateConstructor.Программа.Сборка(Действие`1 контейнер) в D:.net Примеры проектаМай 2021AutofacTest46PrivateConstructorProgram.cs:строка 30 в AutofacTest46PrivateConstructor.Program.Main(строка[] args) в D:.net Примеры проектаМай 2021AutofacTest46PrivateConstructorProgram.cs:строка 16

Хотя я могу «исправить» проблему, изменив модификатор класса конструктора с частного на общедоступный, у меня все еще есть вопросы здесь:

  1. Задокументировано ли где-нибудь такое поведение, а именно с тех пор, как Autofac запрещает частный конструктор, тогда как ранее это было разрешено?
  2. Я хотел бы исключить класс только с непубличным конструктором из регистрации Autofac, как это сделать?

Ответ №1:

Многое произошло с тех пор, как Autofac 2.6 был выпущен восемь лет назад. Одна из таких вещей заключается в том, что мы не рассматриваем частные конструкторы, как вы заметили. Я уверен, что это где-то в одной из заметок о выпуске, но с тех пор мы перешли с кода Google на GitHub, с Subversion на Git, и часть истории была утеряна. Я вижу, что так было, по крайней мере, с 2015 года.

Решение состоит в том, чтобы использовать вашу собственную IConstructorFinder реализацию. Наша версия по умолчанию находится здесь, чтобы вы могли увидеть, как это будет выглядеть. Затем вы можете использовать FindConstructorsWith расширение, чтобы прикрепить свой конструктор finder к регистрации для вашего класса.

 var finder = new MyCustomConstructorFinder();
var builder = new ContainerBuilder();
builder.RegisterType<MyType>().FindConstructorsWith(finder);
 

Комментарии:

1. Возможно, я не указал это четко, но мое намерение состояло в том, чтобы исключить класс с единственным частным конструктором из регистрации Autofac . Я уточню вопрос.

2. Ах. Используйте предложение Where в вызове RegisterAssemblyTypes, как и в LINQ.