Merge pull request #11 from tmccombs/develop

Use bit flags instead of array for options.
This commit is contained in:
Mike Bierlee 2016-06-27 20:19:46 +02:00 committed by GitHub
commit 5943dedc95
5 changed files with 87 additions and 65 deletions

1
.gitignore vendored
View file

@ -15,6 +15,7 @@
/arrayCompletionExample /arrayCompletionExample
/annotationsExample /annotationsExample
/applicationContextExample /applicationContextExample
/registerOnResolveExample
/.project /.project
/.idea /.idea
/*.iml /*.iml

View file

@ -32,7 +32,7 @@ void main() {
* By using the resolve option "registerBeforeResolving" you can register the resolved class * By using the resolve option "registerBeforeResolving" you can register the resolved class
* immediately. Note that any autowired member will not automatically be registered as well. * immediately. Note that any autowired member will not automatically be registered as well.
*/ */
auto violinPlayer = dependencies.resolve!Violin([ResolveOption.registerBeforeResolving]); auto violinPlayer = dependencies.resolve!Violin(ResolveOption.registerBeforeResolving);
/* /*
* You can make the resolve option persistent by setting it on the container with setPersistentResolveOptions(). * You can make the resolve option persistent by setting it on the container with setPersistentResolveOptions().

View file

@ -140,7 +140,7 @@ private void autowireMember(string member, size_t memberIndex, Type)(shared(Depe
static if (isDynamicArray!MemberType) { static if (isDynamicArray!MemberType) {
alias MemberElementType = ElementType!MemberType; alias MemberElementType = ElementType!MemberType;
static if (isOptional) { static if (isOptional) {
auto instances = container.resolveAll!MemberElementType([ResolveOption.noResolveException]); auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
} else { } else {
auto instances = container.resolveAll!MemberElementType; auto instances = container.resolveAll!MemberElementType;
} }
@ -183,7 +183,7 @@ private QualifierType createOrResolveInstance(MemberType, QualifierType, bool cr
return cast(MemberType) instanceFactory.getInstance(); return cast(MemberType) instanceFactory.getInstance();
} else { } else {
static if (isOptional) { static if (isOptional) {
return container.resolve!(MemberType, QualifierType)([ResolveOption.noResolveException]); return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
} else { } else {
return container.resolve!(MemberType, QualifierType); return container.resolve!(MemberType, QualifierType);
} }

View file

@ -47,36 +47,38 @@ class RegistrationException : Exception {
* Options which influence the process of registering dependencies * Options which influence the process of registering dependencies
*/ */
public enum RegistrationOption { public enum RegistrationOption {
none = 0,
/** /**
* Prevent a concrete type being registered on itself. With this option you will always need * Prevent a concrete type being registered on itself. With this option you will always need
* to use the supertype as the type of the dependency. * to use the supertype as the type of the dependency.
*/ */
doNotAddConcreteTypeRegistration, doNotAddConcreteTypeRegistration = 1,
/** /**
* Prevent a concrete type being registered on itself. With this option you will always need * Prevent a concrete type being registered on itself. With this option you will always need
* to use the supertype as the type of the dependency. * to use the supertype as the type of the dependency.
* @deprecated use doNotAddConcreteTypeRegistration instead * @deprecated use doNotAddConcreteTypeRegistration instead
*/ */
DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION = doNotAddConcreteTypeRegistration
} }
/** /**
* Options which influence the process of resolving dependencies * Options which influence the process of resolving dependencies
*/ */
public enum ResolveOption { public enum ResolveOption {
none = 0,
/** /**
* Registers the type you're trying to resolve before returning it. * Registers the type you're trying to resolve before returning it.
* This essentially makes registration optional for resolving by concerete types. * This essentially makes registration optional for resolving by concerete types.
* Resolinvg will still fail when trying to resolve a dependency by supertype. * Resolinvg will still fail when trying to resolve a dependency by supertype.
*/ */
registerBeforeResolving, registerBeforeResolving = 1 << 0,
/** /**
* Does not throw a resolve exception when a type is not registered but will * Does not throw a resolve exception when a type is not registered but will
* return null instead. If the type is an array, an empty array is returned instead. * return null instead. If the type is an array, an empty array is returned instead.
*/ */
noResolveException noResolveException = 1 << 1
} }
/** /**
@ -94,8 +96,8 @@ synchronized class DependencyContainer {
private Registration[] autowireStack; private Registration[] autowireStack;
private RegistrationOption[] persistentRegistrationOptions; private RegistrationOption persistentRegistrationOptions;
private ResolveOption[] persistentResolveOptions; private ResolveOption persistentResolveOptions;
/** /**
* Register a dependency by concrete class type. * Register a dependency by concrete class type.
@ -117,15 +119,27 @@ synchronized class DependencyContainer {
* *
* See_Also: singleInstance, newInstance, existingInstance * See_Also: singleInstance, newInstance, existingInstance
*/ */
public Registration register(ConcreteType)(RegistrationOption[] options = []) { public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) {
return register!(ConcreteType, ConcreteType)(options); return register!(ConcreteType, ConcreteType)(options);
} }
/** /**
* Deprecated: Use register(SuperType, ConcreteType)(RegistrationOption[]) instead * Deprecated: Use register(ConcreteType)(RegistrationOptions) instead.
*/ */
public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption[] options...) { deprecated public Registration register(ConcreteType)(RegistrationOption[] options) {
return register!(SuperType, ConcreteType)(options); return register!(ConcreteType)(buildFlags(options));
}
/**
* Deprecated: Use register(SuperType, ConcreteType)(RegistrationOptions) instead
*/
deprecated public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption first, RegistrationOption[] options...) {
return register!(SuperType, ConcreteType)(first | buildFlags(options));
}
/// ditto
deprecated public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption[] options) {
return register!(SuperType, ConcreteType)(buildFlags(options));
} }
/** /**
@ -145,7 +159,7 @@ synchronized class DependencyContainer {
* *
* See_Also: singleInstance, newInstance, existingInstance, RegistrationOption * See_Also: singleInstance, newInstance, existingInstance, RegistrationOption
*/ */
public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption[] options = []) { public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) {
TypeInfo registeredType = typeid(SuperType); TypeInfo registeredType = typeid(SuperType);
TypeInfo_Class concreteType = typeid(ConcreteType); TypeInfo_Class concreteType = typeid(ConcreteType);
@ -161,8 +175,8 @@ synchronized class DependencyContainer {
auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, this); auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, this);
newRegistration.singleInstance(); newRegistration.singleInstance();
if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) { static if (!is(SuperType == ConcreteType)) {
static if (!is(SuperType == ConcreteType)) { if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) {
auto concreteTypeRegistration = register!ConcreteType; auto concreteTypeRegistration = register!ConcreteType;
concreteTypeRegistration.linkTo(newRegistration); concreteTypeRegistration.linkTo(newRegistration);
} }
@ -172,34 +186,16 @@ synchronized class DependencyContainer {
return newRegistration; return newRegistration;
} }
private bool hasOption(OptionType)(OptionType[] options, shared(OptionType[]) persistentOptions, OptionType option) { private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
foreach (presentOption; persistentOptions) { return ((options | persistentOptions) & option) != 0;
static if (is(OptionType == RegistrationOption)) { }
// DEPRECATED LEGACY COMPATIBILITY - REMOVE REMOVE REMOVE REMOVE REMOVE REMOVE (SOON)
if (presentOption == RegistrationOption.DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION) {
presentOption = RegistrationOption.doNotAddConcreteTypeRegistration;
}
}
if (presentOption == option) { private OptionType buildFlags(OptionType)(OptionType[] options) {
return true; OptionType flags;
} foreach (option; options) {
flags |= option;
} }
return flags;
foreach(presentOption ; options) {
static if (is(OptionType == RegistrationOption)) {
// DEPRECATED LEGACY COMPATIBILITY - REMOVE REMOVE REMOVE REMOVE REMOVE REMOVE (SOON)
if (presentOption == RegistrationOption.DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION) {
presentOption = RegistrationOption.doNotAddConcreteTypeRegistration;
}
}
if (presentOption == option) {
return true;
}
}
return false;
} }
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) { private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) {
@ -260,10 +256,24 @@ synchronized class DependencyContainer {
* --- * ---
* You need to use the resolve method which allows you to specify a qualifier. * You need to use the resolve method which allows you to specify a qualifier.
*/ */
public RegistrationType resolve(RegistrationType)(ResolveOption[] resolveOptions = []) { public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
return resolve!(RegistrationType, RegistrationType)(resolveOptions); return resolve!(RegistrationType, RegistrationType)(resolveOptions);
} }
/**
* Deprecated: Use register(RegistrationType)(ResolveOption) instead.
*/
deprecated public RegistrationType resolve(RegistrationType)(ResolveOption[] resolveOptions) {
return resolve!(RegistrationType)(buildFlags(resolveOptions));
}
/**
* Deprecated: Use register(RegistrationType, QualifierType)(ResolveOption) instead.
*/
deprecated public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption[] resolveOptions) {
return resolve!(RegistrationType, QualifierType)(buildFlags(resolveOptions));
}
/** /**
* Resolve dependencies using a qualifier. * Resolve dependencies using a qualifier.
* *
@ -290,7 +300,7 @@ synchronized class DependencyContainer {
* container.resolve!(Animal, Dog); * container.resolve!(Animal, Dog);
* --- * ---
*/ */
public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption[] resolveOptions = []) { public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
TypeInfo resolveType = typeid(RegistrationType); TypeInfo resolveType = typeid(RegistrationType);
TypeInfo qualifierType = typeid(QualifierType); TypeInfo qualifierType = typeid(QualifierType);
@ -348,7 +358,7 @@ synchronized class DependencyContainer {
* Animal[] animals = container.resolveAll!Animal; * Animal[] animals = container.resolveAll!Animal;
* --- * ---
*/ */
public RegistrationType[] resolveAll(RegistrationType)(ResolveOption[] resolveOptions = []) { public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) {
RegistrationType[] instances; RegistrationType[] instances;
TypeInfo resolveType = typeid(RegistrationType); TypeInfo resolveType = typeid(RegistrationType);
@ -368,6 +378,13 @@ synchronized class DependencyContainer {
return instances; return instances;
} }
/**
* Deprecated: Use resolveAll(RegistrationType)(ResolveOptions) instead.
*/
deprecated public RegistrationType[] resolveAll(RegistrationType)(ResolveOption[] resolveOptions) {
return resolveAll!RegistrationType(buildFlags(resolveOptions));
}
private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) { private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) {
if (resolveType == qualifierType) { if (resolveType == qualifierType) {
if (candidates.length > 1) { if (candidates.length > 1) {
@ -431,35 +448,39 @@ synchronized class DependencyContainer {
/** /**
* Apply persistent registration options which will be used everytime register() is called. * Apply persistent registration options which will be used everytime register() is called.
*/ */
public void setPersistentRegistrationOptions(OptionsTuple...)(OptionsTuple registrationOptions) { public void setPersistentRegistrationOptions(RegistrationOption[] registrationOptions...) {
unsetPersistentRegistrationOptions(); persistentRegistrationOptions = buildFlags(registrationOptions);
foreach (option; registrationOptions) { }
persistentRegistrationOptions ~= option;
} /// ditto
public void setPersistentRegistrationOptions(RegistrationOption options) {
persistentRegistrationOptions = options;
} }
/** /**
* Unsets all applied registration options * Unsets all applied registration options
*/ */
public void unsetPersistentRegistrationOptions() { public void unsetPersistentRegistrationOptions() {
persistentRegistrationOptions = []; persistentRegistrationOptions = RegistrationOption.none;
} }
/** /**
* Apply persistent resolve options which will be used everytime resolve() is called. * Apply persistent resolve options which will be used everytime resolve() is called.
*/ */
public void setPersistentResolveOptions(OptionsTuple...)(OptionsTuple resolveOptions) { public void setPersistentResolveOptions(ResolveOption[] resolveOptions...) {
unsetPersistentResolveOptions(); persistentResolveOptions = buildFlags(resolveOptions);
foreach (option; resolveOptions) { }
persistentResolveOptions ~= option;
} /// ditto
public void setPersistentResolveOptions(ResolveOption options) {
persistentResolveOptions = options;
} }
/** /**
* Unsets all applied registration options * Unsets all applied registration options
*/ */
public void unsetPersistentResolveOptions() { public void unsetPersistentResolveOptions() {
persistentResolveOptions = []; persistentResolveOptions = ResolveOption.none;
} }
} }

View file

@ -497,7 +497,7 @@ version(unittest) {
// Test registering type with option doNotAddConcreteTypeRegistration // Test registering type with option doNotAddConcreteTypeRegistration
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
container.register!(TestInterface, TestClass)([RegistrationOption.doNotAddConcreteTypeRegistration]); container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration);
auto firstInstance = container.resolve!TestInterface; auto firstInstance = container.resolve!TestInterface;
assertThrown!ResolveException(container.resolve!TestClass); assertThrown!ResolveException(container.resolve!TestClass);
@ -506,7 +506,7 @@ version(unittest) {
// Test registering type with option DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION (DEPRECATED) // Test registering type with option DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION (DEPRECATED)
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
container.register!(TestInterface, TestClass)([RegistrationOption.DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION]); container.register!(TestInterface, TestClass)(RegistrationOption.DO_NOT_ADD_CONCRETE_TYPE_REGISTRATION);
auto firstInstance = container.resolve!TestInterface; auto firstInstance = container.resolve!TestInterface;
assertThrown!ResolveException(container.resolve!TestClass); assertThrown!ResolveException(container.resolve!TestClass);
@ -515,7 +515,7 @@ version(unittest) {
// Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing // Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
container.register!TestClass([RegistrationOption.doNotAddConcreteTypeRegistration]); container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration);
container.resolve!TestClass; container.resolve!TestClass;
} }
@ -631,7 +631,7 @@ version(unittest) {
// Test registration when resolving // Test registration when resolving
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
container.resolve!(TestInterface, TestClass)([ResolveOption.registerBeforeResolving]); container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving);
container.resolve!TestClass; container.resolve!TestClass;
} }
@ -653,20 +653,20 @@ version(unittest) {
// Test ResolveOption registerBeforeResolving fails for interfaces // Test ResolveOption registerBeforeResolving fails for interfaces
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
assertThrown!ResolveException(container.resolve!TestInterface([ResolveOption.registerBeforeResolving])); assertThrown!ResolveException(container.resolve!TestInterface(ResolveOption.registerBeforeResolving));
} }
// Test ResolveOption noResolveException does not throw // Test ResolveOption noResolveException does not throw
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
auto instance = container.resolve!TestInterface([ResolveOption.noResolveException]); auto instance = container.resolve!TestInterface(ResolveOption.noResolveException);
assert(instance is null); assert(instance is null);
} }
// ResolveOption noResolveException does not throw for resolveAll // ResolveOption noResolveException does not throw for resolveAll
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
auto instances = container.resolveAll!TestInterface([ResolveOption.noResolveException]); auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException);
assert(instances.length == 0); assert(instances.length == 0);
} }
} }