feat(di): support map literals as providers

This commit is contained in:
Misko Hevery 2016-04-25 21:04:06 -07:00 committed by Martin Probst
parent b1a9e445b3
commit 46cd868827
5 changed files with 55 additions and 7 deletions

View File

@ -0,0 +1,20 @@
import './provider.dart' show Provider;
bool isProviderLiteral(dynamic obj) {
if (obj is Map) {
Map map = obj as Map;
return map.containsKey('provide');
} else {
return false;
}
}
Provider createProvider(dynamic obj) {
Map map = obj as Map;
return new Provider(map['provide'], useClass: map['useClass'],
useValue: map['useValue'],
useExisting: map['useExisting'],
useFactory: map['useFactory'],
deps: map['deps'],
multi: map['multi']);
}

View File

@ -0,0 +1,9 @@
import {Provider} from './provider';
export function isProviderLiteral(obj: any): boolean {
return obj && typeof obj == 'object' && obj.provide;
}
export function createProvider(obj: any): Provider {
return new Provider(obj.provide, obj);
}

View File

@ -391,7 +391,8 @@ export abstract class ReflectiveInjector implements Injector {
* *
* See {@link ReflectiveInjector#fromResolvedProviders} for more info. * See {@link ReflectiveInjector#fromResolvedProviders} for more info.
*/ */
static resolve(providers: Array<Type | Provider | any[]>): ResolvedReflectiveProvider[] { static resolve(providers: Array<Type | Provider | {[k: string]: any} | any[]>):
ResolvedReflectiveProvider[] {
return resolveReflectiveProviders(providers); return resolveReflectiveProviders(providers);
} }
@ -421,7 +422,7 @@ export abstract class ReflectiveInjector implements Injector {
* because it needs to resolve the passed-in providers first. * because it needs to resolve the passed-in providers first.
* See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}. * See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}.
*/ */
static resolveAndCreate(providers: Array<Type | Provider | any[]>, static resolveAndCreate(providers: Array<Type | Provider | {[k: string]: any} | any[]>,
parent: Injector = null): ReflectiveInjector { parent: Injector = null): ReflectiveInjector {
var ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); var ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent); return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
@ -512,7 +513,8 @@ export abstract class ReflectiveInjector implements Injector {
* because it needs to resolve the passed-in providers first. * because it needs to resolve the passed-in providers first.
* See {@link Injector#resolve} and {@link Injector#createChildFromResolved}. * See {@link Injector#resolve} and {@link Injector#createChildFromResolved}.
*/ */
resolveAndCreateChild(providers: Array<Type | Provider | any[]>): ReflectiveInjector { resolveAndCreateChild(
providers: Array<Type | Provider | {[k: string]: any} | any[]>): ReflectiveInjector {
return unimplemented(); return unimplemented();
} }

View File

@ -7,7 +7,7 @@ import {
isArray, isArray,
isType isType
} from 'angular2/src/facade/lang'; } from 'angular2/src/facade/lang';
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {reflector} from 'angular2/src/core/reflection/reflection'; import {reflector} from 'angular2/src/core/reflection/reflection';
import {ReflectiveKey} from './reflective_key'; import {ReflectiveKey} from './reflective_key';
import { import {
@ -26,6 +26,7 @@ import {
} from './reflective_exceptions'; } from './reflective_exceptions';
import {resolveForwardRef} from './forward_ref'; import {resolveForwardRef} from './forward_ref';
import {Provider, ProviderBuilder, provide} from './provider'; import {Provider, ProviderBuilder, provide} from './provider';
import {isProviderLiteral, createProvider} from './provider_util';
/** /**
* `Dependency` is used by the framework to extend DI. * `Dependency` is used by the framework to extend DI.
@ -144,7 +145,7 @@ export function resolveReflectiveProvider(provider: Provider): ResolvedReflectiv
* Resolve a list of Providers. * Resolve a list of Providers.
*/ */
export function resolveReflectiveProviders( export function resolveReflectiveProviders(
providers: Array<Type | Provider | any[]>): ResolvedReflectiveProvider[] { providers: Array<Type | Provider | {[k: string]: any} | any[]>): ResolvedReflectiveProvider[] {
var normalized = _normalizeProviders(providers, []); var normalized = _normalizeProviders(providers, []);
var resolved = normalized.map(resolveReflectiveProvider); var resolved = normalized.map(resolveReflectiveProvider);
return MapWrapper.values( return MapWrapper.values(
@ -188,8 +189,9 @@ export function mergeResolvedReflectiveProviders(
return normalizedProvidersMap; return normalizedProvidersMap;
} }
function _normalizeProviders(providers: Array<Type | Provider | ProviderBuilder | any[]>, function _normalizeProviders(
res: Provider[]): Provider[] { providers: Array<Type | Provider | {[k: string]: any} | ProviderBuilder | any[]>,
res: Provider[]): Provider[] {
providers.forEach(b => { providers.forEach(b => {
if (b instanceof Type) { if (b instanceof Type) {
res.push(provide(b, {useClass: b})); res.push(provide(b, {useClass: b}));
@ -197,6 +199,9 @@ function _normalizeProviders(providers: Array<Type | Provider | ProviderBuilder
} else if (b instanceof Provider) { } else if (b instanceof Provider) {
res.push(b); res.push(b);
} else if (isProviderLiteral(b)) {
res.push(createProvider(b));
} else if (b instanceof Array) { } else if (b instanceof Array) {
_normalizeProviders(b, res); _normalizeProviders(b, res);

View File

@ -532,6 +532,18 @@ export function main() {
expect(provider.resolvedFactories.length).toEqual(2); expect(provider.resolvedFactories.length).toEqual(2);
}); });
it("should support providers as hash", () => {
var provider = ReflectiveInjector.resolve([
{provide: Engine, useClass: BrokenEngine, multi: true},
{provide: Engine, useClass: TurboEngine, multi: true}
])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(2);
});
it("should support multi providers with only one provider", () => { it("should support multi providers with only one provider", () => {
var provider = ReflectiveInjector.resolve( var provider = ReflectiveInjector.resolve(
[new Provider(Engine, {useClass: BrokenEngine, multi: true})])[0]; [new Provider(Engine, {useClass: BrokenEngine, multi: true})])[0];