WPF MVVM с IUnityContainer создает нежелательные множественные экземпляры
Привет! В настоящее время я использую WPF с шаблоном Model/View и IOC, однако у меня возникла проблема с тем, что в настоящее время у меня есть 3 представления, из которых необходимо создать только два, определенные во время выполнения.
В каждом представлении я использую xaml для предоставления объекта для представления следующим образом:
ViewA
<viewmodel:modelA x:Key="viewModel"/>
или же
ViewB
<viewmodel:modelB x:Key="viewModel"/>
...так далее
Также эти представления и их последующие модели имеют следующую иерархию:
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;} }
Теперь с помощью IOC я создаю свой контейнер и регистрирую экземпляр требуемой модели (либо modelB, либо modelC). При попытке создать необходимые представления через container.resolve либо ViewA + ViewB, либо ViewA + ViewC.
Я получаю несколько экземпляров моделей.
Когда я хочу создать только 1 тип, то модель B или модель C.
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>());
Разрешение представлений генерирует больше моделей, когда я хочу, чтобы контейнер использовал уже созданные экземпляры модели и внедрил это в представления. Может ли кто-нибудь помочь или указать мне в правильном направлении,
Спасибо,
2 ответа
Я не совсем уверен, нахожусь ли я на правильном пути, но я посмотрю, смогу ли я все равно помочь.
Глядя на сценарий View/ModelB, я вижу то, что у вас есть:
- Вы регистрируете свой единственный экземпляр ModelB в UnityContainer.
- Вы пытаетесь разрешить новый ViewB
- Создается новый экземпляр ModelB, а не экземпляр на шаге 1
Когда создается объект ViewB, он создает новый ModelB независимо от контейнера единицы. Если вы хотите использовать экземпляр ModelB, который вы ранее зарегистрировали в контейнере Unity, вы можете передать его как зависимость от ViewB, например:
public class ViewB
{
public ViewB(ModelB model){ .. }
}
Если у вас есть эта настройка, то, когда вы попытаетесь разрешить ViewB, ваш ранее зарегистрированный ModelB будет передан.
Надеюсь, это поможет!
Просто если кто-нибудь найдет это позже и захочет узнать, я решил эту проблему, по сути, убрав статическую ссылку на модель представления в моих представлениях.
<viewmodel:modelB x:Key="viewModel"/>
И, как Скотт предлагает сначала зарегистрировать тип, затем экземпляр этого типа, затем разрешить мое унаследованное представление и впоследствии базовое представление (которое при вызове контейнера DI внедряет в зарегистрированный тип). К сожалению, это означало, что в VS2010 я не мог использовать конструктор для создания привязок в xaml, так как мне пришлось установить DataContext из кода в конструкторе представления.
Код:
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);
}
А потом в коде позади для просмотров
public partial class ViewB: UserControl
{
public ViewB(IUnityContainer container)
{
this.DataContext = (ModelB)container.Resolve<ModelB>();
InitializeComponent();
}
}
Это, как я уже сказал, решило проблему, но я надеялся, что был бы более чистый способ использования унаследованных представлений и их моделей. Из которых я все еще ищу, но если это поможет кому-то еще, кто застрял на этом, тогда здорово.