2016-10-13 8 views
0

Я пытаюсь выполнить следующий сценарий инъекции зависимостей с использованием Autofac.Откладывание регистрации собственности с использованием Autofac

Предположим, что у меня есть три класса: A, B и P. Класс A содержит свойство типа P, а также имеет ссылку на B, который необходимо вводить во время выполнения.

class A 
{ 
    private B _b; 

    public P Prop { get; set; } 

    InitializeProp() 
    { ... } 
} 

В то же время, класс B зависит от экземпляра Р:

class B 
{ 
    private P _p; 
} 

Теперь самая важная деталь: мне нужно как-то привнести в B экземпляр P. Однако, что instance должен быть Prop из класса A, который инициализируется только после вызова InitializeProp() в A. Предположим, что InitializeProp() можно назвать позже в течение срока жизни объекта, чем конструктор A.

Этот сценарий возможен с помощью Autofac?

я пытался делать что-то вроде этого, но я получаю круговое эталонное исключение, по-видимому, когда В дальнейшем решен на:

containerBuilder.RegisterType<A>().SingleInstance(); 

containerBuilder.Register<Func<P>>(c => 
{ 
    var a = c.Resolve<A>(); 
    return() => a.Prop; 
}); 

ответ

0

Так в конце концов я понял это, оказывается Autofac умнее я думал.

Не надо было явно зарегистрировать Func Р, но вместо того, чтобы иметь эту упрощенную регистрацию:

builder.RegisterType<A>().SingleInstance(); 

builder.Register(c => 
{ 
    var a = c.Resolve<A>(); 
    return a.Property; 
}); 

builder.RegisterType<B>(); 

В настоящее время в основной программе я могу сделать следующее:

var a = container.Resolve<A>(); 
a.InitializeProperty(); 
a.Execute(); // calls B 
2

Чтобы быть в состоянии схватить Регистрационную проблему, я часто нахожу его полезным для построения графа желаемого объекта вручную в коде. Без использования DI контейнера, это то, что вы хотите достичь:

var p = new P(); 
var a = new A(new B(p)) { P = p }; 

Что вы можете увидеть, что экземпляр P повторно используется на протяжении всего графика для достижения этой цели. Благодаря этим знаниям мы теперь можем определить, что вам нужно сделать, чтобы достичь того, чего вы хотите.

Таким образом, решение заключается в настройке Autofac для повторного использования одного и того же экземпляра P. Поскольку вы зарегистрировали A как SingleInstance, нет другого выбора, кроме регистрации P как SingleInstance, в противном случае вы будете иметь дело с Captive Dependency.

Но если мы сделаем шаг назад, я не вижу причин для P, являющегося собственностью A. На самом деле для использования инъекции свойств существует hardly ever a good reason.

Вы всегда должны использовать инъекцию конструктора. Так что ваши классы должны выглядеть следующим образом:

class A { public A(B b, P p) { } } 
class B { public B(P p) { } } 

Это полностью устраняет проблемы конфигурации, потому что вы можете просто сделать следующее:

containerBuilder.RegisterType<A>().SingleInstance(); 
containerBuilder.RegisterType<B>().SingleInstance(); 
containerBuilder.RegisterType<P>().SingleInstance(); 
+0

В идеале я 'd проектируйте мои классы, как вы предлагаете, P, введенные через конструктор в A и B.Однако мой реальный сценарий сдерживается другими зависимостями и, короче говоря, нет способа обойти наличие свойства P в классе A, которое инициализируется в определенной точке времени жизни A. A реализует интерфейс, в котором объявляется свойство P. –