简体   繁体   English

具有IUnityContainer的WPF MVVM创建不需要的多个实例

[英]WPF MVVM with IUnityContainer creating unwanted multiple instances

Hi I am currently using WPF with the Model/View Pattern and IOC, however I am having a problem with that I currently have a 3 views of which only two will need to be created, determined at runtime. 嗨,我目前将WPF与“模型/视图模式”和IOC一起使用,但是我有一个问题,我目前有3个视图,只需在运行时确定就可以创建两个视图。

In each view I am using the xaml to provide an object for the view like so: 在每个视图中,我都使用xaml为视图提供一个对象,如下所示:

ViewA 视点

<viewmodel:modelA x:Key="viewModel"/>

or 要么

ViewB 视图B

<viewmodel:modelB x:Key="viewModel"/>

...etc ...等等

Also these views and their subsequent models have a hierarchy like: 这些视图及其后续模型的层次结构如下:

class modelA          { public virtual  ConfigA    {get; set;}   } 
class modelB : modelA { public override ConfigB    {get; set;}   }
class modelC : modelB { public override ConfigC    {get; set;}   }

class ConfigA           { public int Test  { get; set;} } 
class ConfigB : ConfigA { public int TestA { get; set;} } 
class ConfigC : ConfigC { public int TestB { get; set;} } 

Now with IOC I am creating my container and registering an instance of the required model (either modelB or modelC). 现在使用IOC创建容器并注册所需模型(模型B或模型C)的实例。 When trying to instantiate the views required, through container.resolve, either ViewA + ViewB or ViewA + ViewC. 尝试通过container.resolve实例化所需的视图时,请使用ViewA + ViewB或ViewA + ViewC。

I get multiple instantiations of the models. 我得到了模型的多个实例。

When I only want 1 type to be created, either modelB or modelC. 当我只想创建一种类型时,无论是modelB还是modelC。

switch (Object)
{
  case 1:
    modelB b = new modelB();
    Container.RegisterInstance<modelB>(b, new ContainerControlledLifetimeManager());
    RegionManager.Regions[RegionNames.MainRegion].Add(Container.Resolve<ViewB>());
  break;
  case 1:
    modelC c = new modelC();
    Container.RegisterInstance<modelC>(c, new ContainerControlledLifetimeManager());
    RegionManager.Regions[RegionNames.MainRegion].Add(Container.Resolve<ViewC>());
  break;
}
RegionManager.Regions[RegionNames.MainRegion].Add(Container.Resolve<ViewA>());

The resolving of the views is generating more models when what I want is the container to use the already constructed instances of the model and inject this into the Views. 当我想要的是容器使用已经构建的模型实例并将其注入到视图中时,视图的解决方案将生成更多模型。 Can anyone help or point me in the right direction, 任何人都可以帮助或指出我正确的方向,

Thanks, 谢谢,

Im not quite sure if Im on the right track but I'll see if I can help anyway. 我不太确定自己是否走上了正确的道路,但我会看看是否可以提供帮助。

Looking at the View/ModelB scenario the way I see what you have is: 以查看我所拥有的方式查看View / ModelB方案是:

  1. You register your single instance of ModelB with the UnityContainer 您可以在UnityContainer中注册ModelB的单个实例
  2. You try to resolve a new ViewB 您尝试解析一个新的ViewB
  3. A new instance of ModelB is created rather than the instance in step 1 being used 将创建一个新的ModelB实例,而不是使用步骤1中的实例

When a ViewB object is created it creates a new ModelB independently of the unity container. 创建ViewB对象时,它将独立于unity容器创建一个新的ModelB。 If you want the instance of ModelB that you previously registered in the unity container to be used you can pass it in as a dependency of ViewB eg 如果要使用之前在unity容器中注册的ModelB实例,则可以将其作为ViewB的依赖项传入,例如

public class ViewB
{
    public ViewB(ModelB model){ .. }
}

If you have this setup then when you try to Resolve a ViewB your previously registered ModelB will be passed in. 如果您有此设置,则当您尝试解析ViewB时,将传递以前注册的ModelB。

Hope that helps! 希望有帮助!

just incase anyone finds this later, and wants to know, I resolved this issue by basically taking out the static reference to the viewmodel in my views. 以防万一以后有人找到并想知道的情况,我基本上通过删除视图中对viewmodel的静态引用来解决了此问题。

<viewmodel:modelB x:Key="viewModel"/>

And as Scott suggests registered first the type, then an instance of that type, then resolving my inherrited view and subsequently the base view (which when called upon by the DI container injects in the registered type). 正如Scott所建议的,首先注册该类型,然后注册该类型的实例,然后解析我的继承视图,然后解析基本视图(当被DI容器调用时,将注入已注册的类型)。 Unfortunately this meant within VS2010 I could not use the designer to create the bindings in xaml, as I had to set the DataContext from code behind in the view constructor. 不幸的是,这意味着在VS2010中,我无法使用设计器在xaml中创建绑定,因为我不得不从视图构造函数中的代码中设置DataContext。

Code: 码:

  UserControl view = null;
  switch (runtimeSetArg)
  {
    case 1:
      Container.RegisterType<modelA, modelB>(new ContainerControlledLifetimeManager());
      Container.RegisterInstance<modelB>(new modelB());
      view = Container.Resolve<viewB>();
      break;
    case 2:
      Container.RegisterType<modelA, modelC>(new ContainerControlledLifetimeManager());
      Container.RegisterInstance<modelC>(new modelC());
      view = Container.Resolve<viewC>();
      break;
    case 3:
      ...
      break;
    case default:
      break;
  }

  if (view != null)
  {
    RegionManager.Regions[RegionNames.MainRegion].Add(Container.Resolve<viewA>());        
    RegionManager.Regions[RegionNames.MainRegion].Add(view);
  }

And then in the code behind for the views 然后在后面的代码中查看

public partial class ViewB: UserControl
{
  public ViewB(IUnityContainer container)
  {
    this.DataContext = (ModelB)container.Resolve<ModelB>();      
    InitializeComponent();
  }
}

This, like I say, resolved the issue but I hoped there would have been a cleaner way of using inherited views and their models. 就像我说的那样,这解决了问题,但是我希望可以有一种更干净的方法来使用继承的视图及其模型。 Of which I am still looking, but if that helps anyone else who is stuck on this, then great. 我仍在寻找其中的东西,但是如果这能帮助其他坚持这一点的人,那就太好了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM