我有两个服务,每个服务都使用不同的 WebSocket作为构造函数参数。我想使用AngularDart的依赖注入传递WebSocket连接,但我不能单独依赖类型(因为我有两个WebSockets)。
如何为每个服务注释或指定哪个特定的WebSocket连接?
让我假装我:
class ServiceOne {
WebSocket socketOne;
ServiceOne(this.socketOne);
}
和
class ServiceTwo {
WebSocket socketTwo; // different connection
ServiceTwo(this.socketTwo);
}
谢谢!
答案 0 :(得分:4)
如果你看看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并希望帮助实现这一目标,请与我联系。
答案 1 :(得分:3)
我还没有看到关于类型名称注入的任何信息。这是'对JS的重大改进,Dart中不再有名字了。 您可以将服务或套接字嵌入两个不同的类中以区分它们。
没有看到一些代码,提出建议有点困难。
示例强>
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());
}
答案 2 :(得分: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}');
}