2014-09-03 2 views
1

Я фактически работаю над проектом с использованием WPF, MEF и Prism. Когда я запускаю приложение, мне нужно экспортировать модуль из контейнера, чтобы открыть окно конфигурации до отображения основного окна. Поэтому код следующим образом:Призма и IEventAggregator: проблема при загрузке модулей

 protected override void OnStartup(StartupEventArgs e) 
     {  base.OnStartup(e); 
       Bootstrapper bootstrapper = new Bootstrapper(); 
       bootstrapper.Run(); 

       var window = bootstrapper.statcontainer.GetExport<Configshell>(); 
       var configview = bootstrapper.statcontainer.GetExport<Module.Module1.View.ConfigView>(); 
       window.Value.Show(); 
       Keyboard.Focus(configview.Value.ok_button); } 

Где bootstrapper.statcontainer является публичной CompositeContainer (выделено с «Maincontainer» из MEFBootstrapper в CreateContainer-метода). Я использую его для экспорта модулей при запуске. Сейчас на GetExport() я получаю следующее первого шанса исключение брошен:

GetExportedValue не может быть вызван до пререквизитов импорта «MyApp.Module.Module2.ViewModels.Module2_Functions..ctor (параметр = "C_Aggregator", ContractName = «Microsoft.Practices.Prism.PubSubEvents.IEventAggregator»).

И это, как там т е р выглядит следующим образом:

[Import] 
    public IEventAggregator Configaggregator; 

    [ImportingConstructor] 
    public Module2_Functions(IEventAggregator C_Aggregator) 
    { 
     this.Configaggregator = C_Aggregator; 
     Configaggregator.GetEvent<FromConfigWindow>(); 
     FromConfigWindow.Instance.Subscribe(receiveStatusFromConfigWindow); 
     Configaggregator.GetEvent<ToConfigWindow>(); 
    } 

I'am помощью EventAggregator опубликовать конфигурацию и имеют тот же CTOR в другом модуле. Путаница заключается в том, что он работал так, пока я не добавил еще один полностью независимый импорт в этот ViewModel. Вот как т е р о ConfigwindowViewModel выглядит следующим образом:

[ImportingConstructor] 
    public ConfigVM(IEventAggregator C_aggregator) 
    { 
     this.Configaggregator = C_aggregator; 
     Configaggregator.GetEvent<ToConfigWindow>(); 
     ToConfigWindow.Instance.Subscribe(actualizeCompStatus); 
     Configaggregator.GetEvent<FromConfigWindow>(); 
    } 

    [Import] 
    public IEventAggregator Configaggregator; 

Эти два события, глядя, как это и так уже работали до 2 дней назад ;-)

[Export] 
public class FromConfigWindow : PubSubEvent<Int16> 
{ 
    private static readonly EventAggregator _eventAggregator; 
    private static readonly FromConfigWindow _event; 

    static FromConfigWindow() 
    { 
     _eventAggregator = new EventAggregator(); 
     _event = _eventAggregator.GetEvent<FromConfigWindow>(); 
    } 

    public static FromConfigWindow Instance 
    { 
     get { return _event; } 
    } 
} 
[Export] 
public class ToConfigWindow : PubSubEvent<Int16> 
{ 
    private static readonly EventAggregator _eventAggregator; 
    private static readonly ToConfigWindow _event; 

    static ToConfigWindow() 
    { 
     _eventAggregator = new EventAggregator(); 
     _event = _eventAggregator.GetEvent<ToConfigWindow>(); 
    } 

    public static ToConfigWindow Instance 
    { 
     get { return _event; } 
    } 
} 

Итак, наконец, проблема не смотрит на меня как EventAggregator не получает instanciated и поэтому исключение получает. Но как я могу обойти это? Или я делаю что-то неправильно в связи с агрегатором в конструкторах?

Я уже пытался изменить все аргументы конструктора с помощью атрибута [Импорт], это также привело к тому же исключению или удалению всех атрибутов [Import] из объектов Configaggregator IEventAggregator в ViewModels.

Проблема аналогична this link here, но в моем случае происходит с EventAggregator из рамки Prism.

Скажите, пожалуйста, если я должен предоставить вам больше частей кода.

ответ

1

Я не уверен, почему вы экспортируете PubSubEvents или сохраняете ссылку на статический новый EventAggregator. Вы должны использовать только один экземпляр EventAggregator (в этом примере), который вы получите из своего контейнера (Prism поместит его там для вас).

Вы должны вернуться к основам и прочитать отличный Prism documentation. Раздел 9 «Связь между слабосвязанными компонентами» для обзора EventAggregator и PubSubEvents.

Если вы хотите создать проект «Голые кости», который имитирует проблему, с которой вы столкнулись, и загрузите ее где-нибудь, я с удовольствием посмотрю на нее.

+1

Поскольку я новичок в Prism, это было то, что я пытался сделать, как некоторые ребята [здесь] (http://www.codeproject.com/Tips/591221/Simple-EventAggregator-in-WPF-PRISM) и [здесь] (http://www.codeproject.com/Articles/355473/Prism-EventAggregator-Sample), но вы правы, я просто протестировал его, и нет необходимости в дополнительном коде в самом классе событий. Я также получаю EventAggregator с помощью ServiceLocator, который отлично работает: 'public IEventAggregator Configaggregator = ServiceLocator.Current.GetInstance ()'; Спасибо за вашу помощь! – Astinels

+0

Блестящий! Добро пожаловать :) – ChrisO

+0

Почему вы получаете EventAggregator из контейнера напрямую, а не импортируете его? – Nicros

1

Похоже, что ошибка связана с тем, что вы не выполнили весь свой импорт до начала операций над ними. Я согласен с ChrisO, вы должны вернуться и проверить документы. Здесь происходит много вещей, которые кажутся слишком сложными.Почему там new EventAggregator()? MEF должен импортировать эту зависимость для вас. Почему все возится с контейнером и получает экспорт? Кажется, вы делаете много работы, о которой должны заботиться MEF и Prism.

+0

Да, так как это мой первый программный проект, и я новичок в Prism, я много чего понимаю, что я сделал сложнее ;-) Вы правы, контейнер лучше доступен через подход ServiceLocator, который я нашел сейчас : 'var container = ServiceLocator.Current.GetInstance (CompositionContainer);' Я еще не тестировал это, просто нашел его [здесь] (http://compositewpf.codeplex.com/discussions/263641) по почте Мигеля Бронзовича. Спасибо за вашу помощь! – Astinels

+0

Несомненно. Но мне действительно интересно, зачем вам контейнер? Работа - это просто вводить примеры того, что вам нужно, где они вам нужны. Если вы пытаетесь получить конкретный экземпляр из контейнера, проверьте MEF ExportFactory https://mef.codeplex.com/wikipage?title=PartCreator, а не на получение контейнера. Я написал около 50 приложений на основе MEF и никогда не нуждался в доступе непосредственно к контейнеру за время композиции. – Nicros

+0

Да, но я сделал это как обходное решение, так как мне нужно было импортировать Импорт в App-Class. И мой Импорт всегда был «нулевым» после того, как завершил загрузку (хотя сборка выполнялась в AggregateCatalog), и появилось исключение. Поэтому я решил получить доступ к Контейнеру, который работал тогда. Другая возможность заключалась бы в переключении главного окна приложения с окном конфигурации, но мне не понравился этот подход, так как он разрушает структуру архитектуры. – Astinels

Смежные вопросы