Prism и IEventAggregator: проблема при загрузке модулей

1

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

        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-Method). Я использую его для экспорта модулей при запуске. Теперь в GetExport() я получаю следующее первое исключение:

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

И вот как выглядит ctor:

    [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>();
    }

Я использую 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], это также порождало то же исключение или удаляло все атрибуты [Import] из объектов Configaggregator IEventAggregator в ViewModels.

Проблема аналогична этой ссылке здесь, но в моем случае это происходит с EventAggregator из структуры Prism.

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

Теги:
wpf
prism
bootstrapper
mef

2 ответа

1
Лучший ответ

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

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

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

  • 1
    Так как я новичок в Prism, это было то, что я пытался сделать как некоторые парни здесь и здесь, но вы правы, я просто протестировал это, и нет необходимости в каком-либо дополнительном коде в самом классе событий. Теперь я также получаю EventAggregator, используя ServiceLocator, который прекрасно работает: public IEventAggregator Configaggregator = ServiceLocator.Current.GetInstance<IEventAggregator>() ; Спасибо за вашу помощь!
  • 0
    Brilliant! Пожалуйста :)
Показать ещё 1 комментарий
1

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

  • 0
    Да, так как это мой первый программный проект и я новичок в Prism, я все время осознаю много вещей, которые я усложнял ;-) Вы правы, Контейнер лучше доступен благодаря подходу ServiceLocator, который я нашел сейчас: var container = ServiceLocator.Current.GetInstance(CompositionContainer); Я не проверял это до сих пор, просто нашел это здесь сообщением Мигеля Бронзовича. Спасибо за вашу помощь!
  • 0
    Конечно. Но что мне действительно интересно, так зачем вам вообще нужен контейнер? Его работа заключается в том, чтобы просто вставлять экземпляры вещей, которые вам нужны, туда, где они вам нужны. Если вы пытаетесь получить конкретный экземпляр из контейнера, проверьте MEF ExportFactory mef.codeplex.com/wikipage?title=PartCreator, а не получите контейнер. Я написал около 50 приложений на основе MEF и никогда не нуждался в доступе непосредственно к контейнеру вне времени композиции.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню