Круговые зависимости в StructureMap - могут ли они быть нарушены с помощью внедрения свойства? - PullRequest
9 голосов
/ 06 мая 2010

У меня есть самый простой вид циклической зависимости в Structuremap - класс A опирается на класс B в своем конструкторе, а класс B опирается на класс A в своем конструкторе. Чтобы разорвать зависимость, я заставил класс B принять класс A как свойство, а не аргумент конструктора, но Structuremap все еще жалуется.

Я видел циклические зависимости, нарушенные с помощью этого метода в других DI-структурах - это проблема с Structuremap или я что-то не так делаю?

Edit: Я должен упомянуть, что свойство класса B является массивом экземпляров класса A, подключенных так:

x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault();

Просто чтобы уточнить, я хочу, чтобы произошла следующая последовательность событий:

  • Построить экземпляр B, "b"
  • Создайте экземпляр A, "a", вставляя "b" в его конструктор
  • Установите для "b.ArrayOfA" значение ["a"]

И я хочу, чтобы все это происходило с использованием автопроводки, если это возможно ...

Редактировать 2: Вот упрощенный пример, в котором используется явное подключение:

interface ILoader { }
interface ILoaderManager { }

class Loader : ILoader
{
    public Loader(ILoaderManager lm) { }
}
class LoaderManager : ILoaderManager
{
    public ILoader Loader { get; set; } // Was an array, but same circular dependency appears here
}

ObjectFactory.Configure
(
    x =>
    {
        x.For<ILoader>.Singleton().Use<Loader>();
        x.For<ILoaderManager>().Singleton().Use<LoaderManager>().OnCreation((c, a) => a.Loader = c.GetInstance<ILoader>());
    }
);

Проверка конфигурации приводит к «Обнаружена проблема двунаправленной зависимости с RequestedType: IocTest2.ILoader ...»

Ответы [ 3 ]

6 голосов
/ 29 октября 2016

StructureMap может обрабатывать двунаправленные ситуации также с помощью обходного пути с использованием отложенного разрешения.

Если у вас есть простая ситуация, такая как ClassA, которая зависит от ClassB и ClassB, которая зависит от ClassA, то вы можете выбрать один из них и преобразовать зависимость как зависимость Lazy. Этот способ сработал для меня, и эта ошибка больше не появлялась ..

public class ClassA
{
    private readonly Lazy<IClassB> _classB;

    public ClassA(Lazy<IClassB> classB)
    {
        _classB = classB;
    }

    public IClassB ClassB => _classB.Value;
}

public class ClassB 
{
    public IClassA _classA { get; set; }

    public ClassB (IClassA classA)
    {
        _classA = classA;
    }
}

Подробнее здесь: http://structuremap.github.io/the-container/lazy-resolution/

3 голосов
/ 06 мая 2010

Самое близкое, что вы можете получить, это что-то вроде этого:

x.For<IB>().Use<B>()
    .OnCreation((ctx, instance) =>
    {
        instance.ArrayOfA = new IA[] {new A(instance) };
    });

Если A имеет другие зависимости, которые вы хотите разрешить из контейнера, вы можете извлечь их из ctx в лямбда-выражении OnCreation.

0 голосов
/ 06 мая 2010

StructureMap, вероятно, выполняет Внедрение сеттера , где он будет заполнять общедоступные настраиваемые свойства для объекта, который он разрешает. Согласно документации,

По умолчанию все общедоступные «сеттеры» являются необязательными, это означает, что эти сеттеры будут установлены, только если они явно настроены для конкретного экземпляра

Так вы случайно настроили свойства для автоматического подключения? Если это так, у вас все еще будет проблема циклической зависимости.

Редактировать: я вижу, что у вас есть. В вашем случае, поскольку в B введено A [], StructureMap должен разрешить зависимость каждого A для B, для которого требуется A [] и т. Д. ...

...