【问题标题】:How to get EventAggregator instance without using constructor injection如何在不使用构造函数注入的情况下获取 EventAggregator 实例
【发布时间】:2017-05-20 03:19:42
【问题描述】:

我有一个看起来像这样的类:

@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() 被调用时,我想根据点击的项目类型发布一条消息。通过让项目实例上的take() 方法返回正确的消息,我已经在不让项目知道 EventAggregator 的情况下一起破解了一种方法。

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

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

然后我会立即通过知道 EA 的视图模型发布此内容。

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

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

【问题讨论】:

    标签: typescript dependency-injection aurelia eventaggregator


    【解决方案1】:

    只是一个快速更新,以显示最终推荐的所有内容。很高兴直接调用 items take 方法并且现在不需要处理一些奇怪的返回消息。

    @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;
        }
    }
    

    然后我可以简单地从 take item 中做到这一点:

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

    【讨论】:

      【解决方案2】:

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

      new Item.Gold(this.eventAggregator)

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

      【讨论】:

      • 当这个问题与武器、金币和战利品有关时会更有趣,不是吗?
      • 我想我会选择其中一个选项并将其包装在项目工厂中。干杯:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 2019-03-27
      相关资源
      最近更新 更多