3

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

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

假设我有:

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

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

谢谢!

4

3 回答 3

4

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

在 AngularJS 中,我们简化了这个问题,并说参数名称是Key. 由于 JS 在源代码中没有类型,这确实是我们对Key.

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

这个问题的解决方案是在类型之上添加注释。所以Annotation+TypeKey. 这可能是这样的:

注意这些都不存在,这只是一个建议,它将如何解决。

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 并希望帮助实现这一点,请联系我。

于 2014-01-21T18:03:02.933 回答
3

我还没有看到有关按类型名称注入的任何信息。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());
}
于 2014-01-20T22:19:12.453 回答
1

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}');
}
于 2014-03-14T09:56:30.650 回答