Регистрация фабричного метода не мешает Autofac вызывать ctor - PullRequest
0 голосов
/ 09 января 2019

У меня есть служба с именем ServiceConfiguration, у которой ctor не по умолчанию. Я пытаюсь зарегистрировать его через Autofac с заводским методом:

builder.Register(c=>LoadConfiguration())
       .As<ServiceConfiguration>();

А вот простой LoadConfiguration метод:

private ServiceConfiguration LoadConfiguration() {
    const string fileName = "app.json";
    var json = File.ReadAllText(fileName, Encoding.UTF8);
    var model = JsonConvert.DeserializeObject<ServiceConfiguration>(json);
    return model;
}

Я ожидаю, что Autofac позвонит на LoadConfiguration, когда я попросил решить ServiceConfiguration Но, похоже, он пытается вызвать ctor на ServiceConfiguration. Например. позвонив по этой линии:

var c = container.Resolve<ServiceConfiguration>();

вызывает эту ошибку:

Autofac.Core.DependencyResolutionException: 'Произошла ошибка во время активация определенной регистрации. Смотрите внутреннее исключение для деталей. Регистрация: Activator = ServiceConfiguration (ReflectionActivator), Services = [ServiceConfiguration], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = Shared, Ownership = OwnedByLifetimeScope '

и InnerException:

DependencyResolutionException: ни один из конструкторов не найден с 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' для типа «ServiceConfiguration» может быть вызван с доступными службами и параметры: Не удается разрешить параметр «JobsConfiguration jobs» конструктора «Void .ctor (JobsConfiguration)».

Можете ли вы узнать, что мне не хватает?

UPDATE: Я не пропускаю регистрацию JobsConfiguration. На самом деле это не регистрируемый тип, и я не хочу его регистрировать. Я вообще не хочу, чтобы ctor вызывали (служба получает сборку из файла json), вместо этого всякий раз, когда кто-то запрашивает ServiceConfiguration, я хочу, чтобы Autofac вызывал LoadConfiguration() и использовал возвращаемое значение.

UPDATE2:

Через некоторое время кажется, что извлечение интерфейса из ServiceConfiguration - скажем, IServiceConfiguration - и регистрация / разрешение интерфейса работает просто отлично. Но я не могу понять, почему! Я имею в виду это:

builder.Register(c=>LoadConfiguration())
       .As<IServiceConfiguration>();

var c = container.Resolve<IServiceConfiguration>();

работает. Но конкретной версии нет. Так почему же? Какая разница?

1 Ответ

0 голосов
/ 09 января 2019

Вы должны стремиться отделить загрузку файлов конфигурации от Композиции объектов. Это означает, что лучше , а не загружать конфигурацию при вызове Resolve. Изменить это тривиально:

ServiceConfiguration configuration = LoadConfiguration();
builder.RegisterInstance(configuration);

Тем не менее, ваша регистрация должна работать:

builder.Register(c => LoadConfiguration())
    .As<ServiceConfiguration>();

Что идентично:

builder.Register(c => LoadConfiguration());

При этой регистрации Autofac не автоматически подключит конструктор ServiceConfiguration, но оставит его предоставленному делегату. Возможно, что-то происходит, что ваше сообщение не показывает.

Я использовал следующее MCVE , используя Autofav 4.8.1, чтобы убедиться, что это работает:

class ServiceConfiguration
{
    public ServiceConfiguration(int a, double b) => Console.WriteLine("ctor called.");
}

static ServiceConfiguration LoadConfiguration() => new ServiceConfiguration(2, 6);

static void Main(string[] args)
{
    var builder = new ContainerBuilder();

    builder.Register(_ => LoadConfiguration()).As<ServiceConfiguration>();

    builder.Build().Resolve<ServiceConfiguration>();
}

Последнее примечание: убедитесь, что ServiceConfiguration не является классом конфигурации всего приложения, который внедряется во многих потребителей. Чтобы понять, что не так с классами конфигурации всего приложения, прочитайте этот Q / A .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...