如何在不使用构造函数注入的情况下获取 EventAggregator 实例

How to get EventAggregator instance without using constructor injection

我有一个 class 看起来像这样:

@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() 时,我想根据单击的项目类型发布消息。我通过在项目实例 return 上获取正确消息的 take() 方法,在不让项目知道 EventAggregator 的情况下共同破解了一种执行此操作的方法。

Gold 然后这样实现: take() { return new GoldTaken(this) };

然后Weapon是这样实现的: take() { return new WeaponTaken(this) };

然后我立即通过了解 EA 的视图模型发布它。

如果项可以自己发布此消息会更好更清楚,但为了获得 EventAggregator,我只知道通过构造函数注入正确的实例。这不是很理想,因为我不想在每次更新和项目时都传递这个。

有没有办法让我从项目实例的 take 方法中获取正确的 EventAggregator 单例?

您可以自己注入事件聚合器。

new Item.Gold(this.eventAggregator)

另一种选择是使用 Aurelia 的 DI 容器来创建项目并允许 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);
    } 
}

weapon.js

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

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

只是一个快速更新,以显示最终推荐的结果。很高兴直接调用 items take 方法,现在不需要处理一些奇怪的 return 消息。

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