Windsor LifeStyle - Shared instance per Graph

我们两清 提交于 2019-11-26 22:10:34

问题


I have 2 types of ViewModel's

      public class ViewModelA 
      {
          IService service;
          private ViewModelB childViewModel; 

           public ViewModelA(IService service,ViewModelB childViewModel)
           {
               this.service = service;
               this.childViewModel = childViewModel;
           }

           public ViewModelB ChildViewModel
           {
                get { return childViewModel; } 
            } 
      }  

      public class ViewModelB 
      {
          IService serivce;  
          public ViewModelB(IService service)
          {
              this.service = service;
          }  
      } 

I have a Service registered into a Windsor Container :

     public class Service : IService {}

     container.Register(Component.For<IService>()
                  .ImplementedBy<Service >().LifeStyle.Transient); 

I want ViewModelA and ViewModelB to share the same instance of IService.

I Do not wan't all instances of ViewModelA and ViewModelB to share the same instance.

Each Parent/Child Pair would have his own instance , i wan't to achieve this using DependencyInjection can this be done ?

I wan't this to be be done through Dependency Injection since i have an entire hierarchy of ViewModels under A and not just one (B) viewmodel.

VM A -> VM B -> VM C -> VM D ... (and let's say ill go over the all alphabet) all these need to share the same instance of IService.

and another instance of A and it's decedents would share a a different instance of IService.


回答1:


You may be able to use Scoped Lifestyles. Here's an example of some unit tests that seem to do what you want:

[Fact]
public void VMsInSameScopeSharesService()
{
    var container = new WindsorContainer();
    container.Register(Component.For<ViewModelA>().LifestyleTransient());
    container.Register(Component.For<ViewModelB>().LifestyleTransient());
    container.Register(Component
        .For<IService>().ImplementedBy<NullService>().LifestyleScoped());

    using (container.BeginScope())
    {
        var a = container.Resolve<ViewModelA>();

        Assert.Equal(a.service, a.childViewModel.service);
    }
}

[Fact]
public void VMsInDifferentScopesDoNotShareServices()
{
    var container = new WindsorContainer();
    container.Register(Component.For<ViewModelA>().LifestyleTransient());
    container.Register(Component.For<ViewModelB>().LifestyleTransient());
    container.Register(Component
        .For<IService>().ImplementedBy<NullService>().LifestyleScoped());

    IService service1;
    using (container.BeginScope())
    {
        var a = container.Resolve<ViewModelA>();

        service1 = a.service;
    }
    IService service2;
    using (container.BeginScope())
    {
        var a = container.Resolve<ViewModelA>();

        service2 = a.service;
    }

    Assert.NotEqual(service1, service2);
}

However, this is quite an exotic requirement, which makes me wonder why you want it to behave exactly like this, or if you couldn't structure your code in a way that would make this simpler.




回答2:


What worked for me is using : LifeStyle BoundTo

    container.Register(Component.For<IService>()
            .ImplementedBy<Service>()
            .LifeStyle.BoundTo<ViewModelA>());

Graph :

     public class ViewModelAConductor 
     {
         private List<ViewModelA> rootViewModels = new List<ViewModelA>();
         public ViewModelAConductor()
         {
              ViewModelA a1 = container.Resolvce<ViewModelA>(); 
              rootViewModels.Add(a1);

              ViewModelA a2 = container.Resolvce<ViewModelA>(); 
              rootViewModels.Add(a2); 
         }
     }

     public class ViewModelA
     {
          ViewModelB viewModelB;
          IService service;

          public ViewModelA(IService service,ViewModelB viewModelB) 
          {
              this.service = service;
              this.viewModelB = viewModelB;
          }               
     }

     public class ViewModelB
     {
          ViewModelC viewModelC;
          IService service;

          public ViewModelA(IService service,ViewModelC viewModelC) 
          {
              this.service = service;
              this.viewModelC = viewModelC;
          }               
     }  

     public class ViewModelC
     {
          IService service;

          public ViewModelA(IService service) 
          {
              this.service = service;                 
          }               
     }  

All ViewModels injected under the Graph of a1 have the same instance of IService.

All ViewModels injected under the Graph of a2 have the same instance of IService.



来源:https://stackoverflow.com/questions/25064516/windsor-lifestyle-shared-instance-per-graph

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!