2017-01-05 11 views
1

У меня есть класс, который выглядит следующим образом:Как получить экземпляр 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) };

Я тогда просто опубликовать это сразу через ViewModel, который знает о EA.

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

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

ответ

3

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

new Item.Gold(this.eventAggregator)

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

Вот пример: 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); 
    } 
} 

weapon.js

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

@inject(EventAggregator) 
export class Weapon { 
    name = ''; 
    constructor(ea) { 
    this.ea = ea; 
    } 
} 
+1

Это смешнее, когда вопрос касается оружия, золота и бабло, не так ли? –

+0

Думаю, я поеду с одним из этих вариантов и оберну его на фабрику товаров. Приветствия :) – 4imble

0

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

@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 Changeset]