Как внедрить один и тот же экземпляр одного компонента в несколько других? - PullRequest
0 голосов
/ 09 декабря 2011

Используя Autofac, у меня есть следующий сценарий:

public class MainClass
{
     public delegate MainClass Factory();
     public MainClass(Report report, SecondaryClass secClass)
     {
         Report=report;
         SecondaryClass = secClass;
     }
     public Report Report {get; private set;}
     public SecondaryClass SecondaryClass {get; private set;}
}

public class SecondaryClass
{   
     public SecondaryClass(Report report)
     {
         Report=report;
     }
     public Report Report {get; private set;}
}

Чего я хотел бы добиться, так это чтобы каждый раз, когда я вызывал делегат Factory () в MainClass, и MainClass, и SecondaryClass внедрялись в один и тот же экземпляр Report.

В основном

public void MyMethod()
{
     var myMainClass = _MainClassFactory.Invoke();
     //How do I do achieve this????
     Debug.Assert (object.ReferenceEquals(myMainClass.Report , myMainClass.SecondaryClass.Report));
}

Как настроить MainClass и SecondaryClass? Моя текущая конфигурация следующая, но, кажется, она не достигает того, чего я хочу. Фактически, каждый раз, когда я вызываю метод Factory, я получаю один и тот же экземпляр Report.

        builder.RegisterType<MainClass>().AsSelf();
        builder.RegisterType<SecondaryClass>().AsSelf();
        builder.RegisterType<Report>().AsSelf().InstancePerLifetimeScope();

Ответы [ 2 ]

1 голос
/ 11 декабря 2011

Как обычно, это зависит.

Если вы хотите выразить тот факт, что MainClass преднамеренно требует того же экземпляра Report, что и экземпляр SecondaryClass, то вы должны либо взять Report из SecondaryClass, поскольку @adrift имеет предлагается в комментариях или использовать параметризацию:

public class MainClass
{
 public delegate MainClass Factory();
 public MainClass(Report report, Func<Report, SecondaryClass> secClassFactory)
 {
     Report=report;
     SecondaryClass = secClassFactory(report);
 }
 public Report Report {get; private set;}
 public SecondaryClass SecondaryClass {get; private set;}
}

public class SecondaryClass
{   
 public SecondaryClass(Report report)
 {
     Report=report;
 }
 public Report Report {get; private set;}
}

( см. Ссылку на вики-автофак ) С этими подходами вы прямо показываете, что вам требуется, чтобы два объекта использовали один и тот же Report.

Если ваши SecondaryClass и MainClass не заботятся о том, используют ли они один и тот же Report, и вы просто хотите, чтобы они поделились им, вы можете использовать отдельную область действия, как предложил @adrift. Но имейте в виду, что если вы используете другие компоненты, которые зависят от Report, они также получат тот же экземпляр внутри этой области действия. Это будет своего рода синглтон внутри прицела.

Я не рекомендую использовать область действия, если ваши компоненты зависят от использования одного и того же экземпляра. Если бы вы это сделали, требование было бы запутано, что плохо.

1 голос
/ 09 декабря 2011

Если вы разрешите MainType в пределах срока действия, один и тот же экземпляр Report будет использоваться для MainClass и SecondaryClass.

Итак, в вашем заводском методе вы можете сделать что-то вроде этого:

using (var lifetime = container.BeginLifetimeScope())
{
    return container.Resolve<MainClass>();
}
...