【问题标题】:How can I Dependency Inject based on type and name, with AngularDart?如何使用 AngularDart 基于类型和名称进行依赖注入?
【发布时间】:2014-01-20 21:36:40
【问题描述】:

我有两个服务,每个都接受一个不同的 WebSocket 作为构造函数参数。我想使用 AngularDart 的依赖注入来传入 WebSocket 连接,但我不能单独依赖类型(因为我有两个 WebSocket)。

如何注释或指定每个服务应该使用哪个特定的 WebSocket 连接?

假设我有:

class ServiceOne {
  WebSocket socketOne;
  ServiceOne(this.socketOne);
}

class ServiceTwo {
  WebSocket socketTwo; // different connection
  ServiceTwo(this.socketTwo);
}

谢谢!

【问题讨论】:

  • websockets 在应用程序启动时打开并保持打开状态?您想让它们在构造函数引用它们的任何地方都可用吗?还是应该在注入 websocket 时才打开连接?
  • 我添加了示例。如果这不是您想要的,请添加评论。

标签: dart angular-dart


【解决方案1】:

如果你看一下 GUICE,这个问题就很好理解了。 (https://code.google.com/p/google-guice/) 问题是,当您检索实例时,您需要有某种 Key(这就是 GUICE 所说的)。您可以通过多种方式获得Key

在 AngularJS 中,我们简化了问题,并表示参数名称为Key。由于 JS 在源代码中没有类型,这确实是我们对 Key 的唯一选择。

在 AngualDart 中,我们对其进行了改进并将Type 用作Key。这样做的好处是参数名称无关紧要。但这会产生一个问题,即您只能注入每个Type 中的一个。对于自定义类型,这没什么大不了的,但是只有一个 String 配置类型会成为问题。

解决这个问题的方法是在类型之上添加注解。所以Annotation + Type 就是Key。以下是可能的样子:

注意目前还不存在,这只是一个提案,如何解决。

class MyClass {
  MyClass(@Url String url, @Secret String secret) { ... }
}

Module module = new Module();
module.value(key(String, [Url]), 'http://server.com/...');
module.value(key(String, [Secret]), 'A89B42C');

请求由于尚未实施,如果您热衷于帮助 AngularDart 并希望帮助实现这一目标,请与我联系。

【讨论】:

  • 这实际上非常有用。
  • @misko-hevery 与您联系的最佳方式是什么? :)
【解决方案2】:

我还没有看到有关按类型名称进行注入的任何内容。 Dart 中不再有名称,这是对 JS 的“最大”改进。 您可以将服务或套接字嵌入两个不同的类中以区分它们。

如果没有看到一些代码,很难提出建议。

示例

library main;

import 'dart:html';
import 'package:angular/angular.dart';
import 'package:di/di.dart';


/**
 * usage examples
 */

class ServiceOne {
  WebSocketWrapper1 socketOne;
  ServiceOne(this.socketOne);

  void doSomething() {
    socketOne.ws.xxx();
  }
}

class ServiceTwo {
  WebSocketWrapper2 socketTwo; // different connection
  ServiceTwo(this.socketTwo);

    void doSomething() {
      socketTwo.ws.xxx();
    }
  }
}    

@NgController(
    selector: '[ng-controller=alert-demo-ctrl]',
    publishAs: 'ctrl')
class AlertDemoController {
  WebSocketOnDemandWrapper1 _wsodw1;

  AlertDemoController(this._wsodw1) {
  }

  String sendData() {
    _wsodw1.ws.send("somedata");
  }
}

@NgController(
    selector: '[ng-controller=accordion-demo-ctrl]',
    publishAs: 'ctrl')
class AccordionDemoController {
  WebSocketOnDemandWrapper2 _wsodw2;

  AccordionDemoController(this._wsodw2) {
  }

  String sendData() {
    _wsodw2.ws.send("somedata");
  }
}


/**
 * injectable WebSockets
 */

class WebSocketWrapper1 {
  WebSocket ws;
  WebSocketWrapper1(this.ws);
}

class WebSocketWrapper2 {
  WebSocket ws;
  WebSocketWrapper2(this.ws);
}

class WebSocketOnDemandWrapper1 {
  WebSocket ws;
  WebSocketOnDemandWrapper1(){
    ws = new WebSocket('ws://127.0.0.1:1337/ws');
  }
}

class WebSocketOnDemandWrapper2 {
  WebSocket ws;
  WebSocketOnDemandWrapper2(){
    ws = new WebSocket('ws://127.0.0.1:3173/ws');
  }
}


class MyAppModule extends Module {
  MyAppModule() {
    type(ServiceOne);
    type(ServiceTwo);
    type(AlertDemoController);
    type(AccordionDemoController);
    type(WebSocketOnDemandWrapper1); // connect on demand
    type(WebSocketOnDemandWrapper2); // connect on demand

    // start connection on app startup and provide this connection when requested
    value(WebSocketWrapper1, new WebSocketWrapper1(new WebSocket('ws://127.0.0.1:1337/ws'))); 
    value(WebSocketWrapper2, new WebSocketWrapper2(new WebSocket('ws://127.0.0.1:3173/ws')));
  }
}

void main() {
  ngBootstrap(module: new MyAppModule());
}

【讨论】:

  • 我添加了一个简单的例子。如果不需要的话,我宁愿不必创建 WebSocket 的子类。
【解决方案3】:

DI 0.0.34 使用注释获得了对此用例的特殊支持

不支持带参数的注释。我不确定这是否仍在计划中 (https://github.com/angular/di.dart/issues/46)

我还添加了一个示例,现在如何将原语与 DI 一起使用。 (不确定这是否很有用)

import 'package:di/di.dart';
import 'package:di/dynamic_injector.dart';

/**
 * Annotation used to mark classes for which static type factory must be
 * generated. For testing purposes not all classes are marked with this
 * annotation, some classes are included in @Injectables at the top.
 */
class Injectable {
  const Injectable();
}

/**
 * Some dummy WebSocket class (just for demonstration)
 */
@Injectable()
class WebSocket {
  String url;
  WebSocket(this.url);
}

/**
 * Allows to mark an injectable as 'one'
 */
class One {
  const One();
}

/**
 * Allows to mark an injectable as 'two'
 */
class Two {
  const Two();
}

/**
 * A class that implements updates.
 * It needs a websocket marked as 'one'
 */
class Updates {
  WebSocket ws;
  Updates(@One() this.ws);
}


/**
 * A class that implements chats.
 * It needs a websocket marked as 'two'
 */
class Chat {
  WebSocket ws;
  Chat(@Two() this.ws);
}

/**
 * The application module
 */
class AppModule extends Module {
  AppModule() {
    value(String, 'http://www.google.com', withAnnotation: AjaxUrl);
    value(int, 8080, withAnnotation: ServerPort);
    value(int, 1000);
    factory(WebSocket, (Injector i) => new WebSocket('ws://game.example.com:12010/updates'), withAnnotation: One);
    factory(WebSocket, (Injector i) => new WebSocket('ws://chat.example.com/games'), withAnnotation: Two);
    type(Chat);
    type(Updates);
  }

  Injector _injector;
  Injector get injector {
    if (_injector == null) {
      _injector = new DynamicInjector(modules: [this]);

      // Static injector => comment in and comment out above
      //      _injector = new StaticInjector(modules: [this],
      // typeFactories: type_factories_gen.typeFactories);
    }
    return _injector;
  }
}

/**
 * Allows to mark a String as ajax url
 * Just to demonstrate how to use primitive types with DI
 */
class AjaxUrl {
  const AjaxUrl();
}

/**
 * Allows to mark an int as server port
 * Just to demonstrate how to use primitive types with DI
 */
class ServerPort {
  const ServerPort();
}


void main(List<String> args) {
  var module = new AppModule();

  print('AjaxUrl: ${module.injector.get(String, AjaxUrl)}');
  print('ServerPort: ${module.injector.get(int, ServerPort)}');
  // primitives without annotation are not supported and throw an exception
  // print('int: ${module.injector.get(int)}'); 
  print('Chat: ${module.injector.get(Chat).ws.url}');
  print('Updates: ${module.injector.get(Updates).ws.url}');
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 2014-01-09
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    相关资源
    最近更新 更多