问题
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