Как получить экземпляр EventAggregator без использования внедрения конструктора

У меня есть класс, который выглядит так:

@inject(EventAggregator)
export class LootStack {
    stack: Array<Item.Loot> = [];

    constructor(private eventAggregator: EventAggregator) {
        this.eventAggregator.subscribe(MonsterKilled, () => {
            this.stack.push(new Item.Gold()); 
            this.stack.push(new Item.Weapon("Thunderfury, Blessed Blade of the Windseeker"));
        });
    }

    takeItem(lootItem: Item.Loot){
        this.eventAggregator.publish(lootItem.take()) <--- returns specific message
        this.stack.remove(lootItem);
    }
}

Когда вызывается takeItem(), я хочу опубликовать сообщение на основе типа элемента, на который нажали. Я взломал способ сделать это без того, чтобы элемент знал об EventAggregator, заставив метод take() экземпляра элемента вернуть правильное сообщение.

Затем Gold реализуется следующим образом: take() { return new GoldTaken(this) };

И тогда Weapon реализуется так: take() { return new WeaponTaken(this) };

Затем я сразу же публикую это через модель представления, которая знает о советнике.

Было бы лучше и понятнее, если бы элементы могли публиковать это сообщение сами, но для того, чтобы получить EventAggregator, я знаю только внедрение правильного экземпляра через конструктор. Это не так желательно, так как я не хочу передавать это каждый раз, когда я обновляюсь и добавляю элемент.

Есть ли способ получить правильный синглтон EventAggregator из моего метода взятия экземпляра элемента?


person 4imble    schedule 05.01.2017    source источник


Ответы (2)


Вы можете внедрить агрегатор событий в себя.

new Item.Gold(this.eventAggregator)

Другой вариант — использовать контейнер DI Aurelia для создания элементов и позволить контейнеру DI внедрить в них агрегатор событий для вас. После этого вы, вероятно, захотите установить свойство имени.

Вот пример: https://gist.run?id=e1f5a3159a1a7464140f5e3b0582c18e

app.js

import {inject, Container} from 'aurelia-framework';
import {Weapon} from './weapon';

@inject(Container)
export class App {

    constructor(container){ 
      const weapon = container.get(Weapon);

      weapon.name = 'Thunderfury, Blessed Blade of the Windseeker';

      console.log(weapon);
    } 
}

оружие.js

import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';

@inject(EventAggregator)
export class Weapon {
  name = '';
  constructor(ea) {
    this.ea = ea;
  } 
}
person Ashley Grant    schedule 05.01.2017
comment
Смешнее, когда вопрос связан с оружием, золотом и добычей, не так ли? - person Fabio Luz; 05.01.2017
comment
Я думаю, что я выберу один из этих вариантов и оберну его в фабрику предметов. Ваше здоровье :) - person 4imble; 09.01.2017

Просто быстрое обновление, чтобы показать, как все это выглядело с рекомендацией в конце. Приятно вызывать прямо метод взятия элементов и не иметь какого-то странного возвращаемого сообщения для обработки сейчас.

@autoinject
export default class ItemFactory {
    constructor(private eventAggregator: EventAggregator) { }

    buildGold(): Item.Gold {
        let newGold = new Item.Gold(this.eventAggregator);
        newGold.value = Dice.d20();
        newGold.template = "gold";
        return newGold;
    }

    buildWeapon(name: string): Item.Weapon {
        let newWeapon = new Item.Weapon(this.eventAggregator);
        newWeapon.name = name;
        newWeapon.damage = Dice.d20();
        newWeapon.template = "weapon";
        return newWeapon;
    }
}

Тогда я могу просто сделать это из взятого элемента:

@autoinject
export class LootStack {
    stack: Array<Item.Loot> = [];

    constructor(private eventAggregator: EventAggregator, private itemFactory: ItemFactory) {
        this.eventAggregator.subscribe(MonsterKilled, () => {
            this.stack.push(itemFactory.buildGold()); 
            this.stack.push(itemFactory.buildWeapon("Thunderfury, Blessed Blade of the Windseeker"));
        });
    }

    takeItem(lootItem: Item.Loot){
        lootItem.take();
        this.stack.remove(lootItem);
    }
}

[Набор изменений Github]

person 4imble    schedule 09.01.2017