Как обрабатывать циклические ссылки с помощью Autofac 2.4.5? - PullRequest
5 голосов
/ 31 мая 2011

На вики-странице autofac о Циркулярные ссылки сказано использовать:

cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties);

Но похоже, что ActivatedHandler больше не существует в 2.4.5. Покопавшись в источнике, я нашел реализацию этого класса, и поэтому вместо этого я включил реализацию метода в OnActivation. К сожалению, это все еще не работает.

Я собрал здесь минимальное повторение, похожее на то, что было на вики-странице.

class M
{
    public VM VM { get; set; }

    public M()
    {
    }
}

class VM
{
    public VM(M m)
    {
    }
}

[Fact]
void CanResolveCircular()
{
    ContainerBuilder builder = new ContainerBuilder();

    builder.RegisterType<VM>();
    builder.RegisterType<M>().OnActivated(e => e.Context.InjectUnsetProperties(e.Instance));

    using (var container = builder.Build())
    {
        var m = container.Resolve<M>();
        Assert.NotNull(m);
    }
}

Этот код все еще выдает исключение переполнения стека при попытке Resolve. Что мне не хватает? Как правильно использовать Autofac для обработки циклических зависимостей?

Ответы [ 2 ]

7 голосов
/ 31 мая 2011

В документации Autofac для циклических зависимостей указано:

Обратите внимание, настраивать не имеет смысла этот сценарий, если оба класса зарегистрировано с фабричной областью.

Обе ваши регистрации M и VM имеют значение InstancePerDependency (ранее известное как FactoryScope), поэтому это утверждение относится к вашему сценарию. В результате вы получаете бесконечный цикл создания экземпляров M и VM.

Если вы хотите, чтобы введенное свойство VM принимало тот же экземпляр из M, который вы разрешаете, вы должны изменить время жизни M на что-то отличное от InstancePerDependency (например, SingleInstance). Это показано ниже:

builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance();

Примечание. Я также использую более свежий метод расширения PropertiesAutowired (true). Вы можете использовать это вместо кода OnActivation в вашем репро.

Если вам не нужен один экземпляр M на приложение, вы можете установить LifetimeScope и использовать InstancePerLifetimeScope.

5 голосов
/ 03 мая 2014

Для всех, кто заинтересован, вот новый способ сделать это:

class DependsByProp1
{
    public DependsByProp2 Dependency { get; set; }
}

class DependsByProp2
{
    public DependsByProp1 Dependency { get; set; }
}

// ...

var cb = new ContainerBuilder();
cb.RegisterType<DependsByProp1>()
      .InstancePerLifetimeScope()
      .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
cb.RegisterType<DependsByProp2>()
      .InstancePerLifetimeScope()
      .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);

Свойство / Зависимости от собственности

...