Reformat code to use otbs brace style

It's more compact and more common in the coding world these days.
This commit is contained in:
Mike Bierlee 2023-03-07 01:24:18 +03:00
parent 6d1bf44d28
commit 9b05aa3af9
30 changed files with 673 additions and 1308 deletions

View file

@ -1,3 +1,3 @@
{
"dfmt.braceStyle": "allman"
"dfmt.braceStyle": "otbs"
}

View file

@ -37,7 +37,7 @@ import poodinis;
class Driver {}
interface Database {};
interface Database {}
class RelationalDatabase : Database {
private Driver driver;

View file

@ -12,53 +12,42 @@ import std.digest.md;
import std.stdio;
import std.conv;
class SecurityAuditor
{
public void submitAudit()
{
class SecurityAuditor {
public void submitAudit() {
writeln("Hmmmyes I have received your audit. It is.... adequate.");
}
}
class SuperSecurityDevice
{
class SuperSecurityDevice {
private int seed;
public this()
{
public this() {
auto randomGenerator = Random(unpredictableSeed);
seed = uniform(0, 999, randomGenerator);
}
public string getPassword()
{
public string getPassword() {
return to!string(seed) ~ "t1m3sp13!!:";
}
}
class SecurityManager
{
class SecurityManager {
@Autowire private SuperSecurityDevice levelOneSecurity;
@Autowire @AssignNewInstance private SuperSecurityDevice levelTwoSecurity;
@Autowire @OptionalDependency private SecurityAuditor auditor;
public void doAudit()
{
if (auditor !is null)
{
public void doAudit() {
if (auditor !is null) {
auditor.submitAudit();
}
else
{
} else {
writeln("I uh, will skip the audit for now...");
}
}
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope
dependencies.register!SecurityManager;
@ -68,12 +57,9 @@ void main()
writeln("Password for user one: " ~ manager.levelOneSecurity.getPassword());
writeln("Password for user two: " ~ manager.levelTwoSecurity.getPassword());
if (manager.levelOneSecurity is manager.levelTwoSecurity)
{
if (manager.levelOneSecurity is manager.levelTwoSecurity) {
writeln("SECURITY BREACH!!!!!"); // Should not be printed since levelTwoSecurity is a new instance.
}
else
{
} else {
writeln("Security okay!");
}

View file

@ -9,64 +9,50 @@ import poodinis;
import std.stdio;
class TownSquare
{
class TownSquare {
@Autowire private MarketStall marketStall;
public void makeSound()
{
public void makeSound() {
marketStall.announceGoodsForSale();
}
}
interface Goods
{
interface Goods {
public string getGoodsName();
}
class Fish : Goods
{
public override string getGoodsName()
{
class Fish : Goods {
public override string getGoodsName() {
return "Fish";
}
}
class MarketStall
{
class MarketStall {
private Goods goods;
this(Goods goods)
{
this(Goods goods) {
this.goods = goods;
}
public void announceGoodsForSale()
{
public void announceGoodsForSale() {
writeln(goods.getGoodsName() ~ " for sale!");
}
}
class ExampleApplicationContext : ApplicationContext
{
class ExampleApplicationContext : ApplicationContext {
@Autowire private Goods goods;
public override void registerDependencies(shared(DependencyContainer) container)
{
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!(Goods, Fish);
container.register!TownSquare;
}
@Component public MarketStall marketStall()
{
@Component public MarketStall marketStall() {
return new MarketStall(goods);
}
}
void main()
{
void main() {
auto container = new shared DependencyContainer();
container.registerContext!ExampleApplicationContext;

View file

@ -9,50 +9,39 @@ import poodinis;
import std.stdio;
interface Pie
{
interface Pie {
public void eat();
}
class BlueBerryPie : Pie
{
public override void eat()
{
class BlueBerryPie : Pie {
public override void eat() {
writeln("Nom nom nom. I like this one!");
}
}
class ApplePie : Pie
{
public override void eat()
{
class ApplePie : Pie {
public override void eat() {
writeln("Nom nom nom. These aren't real apples...");
}
}
class CardboardBoxPie : Pie
{
public override void eat()
{
class CardboardBoxPie : Pie {
public override void eat() {
writeln("Nom nom nom. This... is not a pie.");
}
}
class PieEater
{
class PieEater {
@Autowire private Pie[] pies;
public void eatThemAll()
{
foreach (pie; pies)
{
public void eatThemAll() {
foreach (pie; pies) {
pie.eat();
}
}
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!(Pie, BlueBerryPie);
dependencies.register!(Pie, ApplePie);

View file

@ -7,64 +7,52 @@
import std.stdio;
class Scheduler
{
class Scheduler {
private Calendar calendar;
// All parameters will autmatically be assigned when Scheduler is created.
this(Calendar calendar)
{
this(Calendar calendar) {
this.calendar = calendar;
}
public void scheduleJob()
{
public void scheduleJob() {
calendar.findOpenDate();
}
}
class Calendar
{
class Calendar {
private HardwareClock hardwareClock;
// This constructor contains built-in type "int" and thus will not be used.
this(int initialDateTimeStamp, HardwareClock hardwareClock)
{
this(int initialDateTimeStamp, HardwareClock hardwareClock) {
}
// This constructor is chosen instead as candidate for injection when Calendar is created.
this(HardwareClock hardwareClock)
{
this(HardwareClock hardwareClock) {
this.hardwareClock = hardwareClock;
}
public void findOpenDate()
{
public void findOpenDate() {
hardwareClock.doThings();
}
}
class HardwareClock
{
class HardwareClock {
// Parameterless constructors will halt any further selection of constructors.
this()
{
this() {
}
// As a result, this constructor will not be used when HardwareClock is created.
this(Calendar calendar)
{
this(Calendar calendar) {
throw new Exception("This constructor should not be used by Poodinis");
}
public void doThings()
{
public void doThings() {
writeln("Things are being done!");
}
}
void main()
{
void main() {
import poodinis; // Locally imported to emphasize that classes do not depend on Poodinis.
auto dependencies = new shared DependencyContainer();

View file

@ -8,12 +8,10 @@
import poodinis;
import std.stdio;
class Doohickey
{
class Doohickey {
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!Doohickey.initializedBy({
writeln("Creating Doohickey via initializer delegate.");

View file

@ -9,44 +9,34 @@ import poodinis;
import std.stdio;
class ADependency
{
@PostConstruct public void postConstructor()
{
class ADependency {
@PostConstruct public void postConstructor() {
writeln("The dependency is created.");
}
public void callMe()
{
public void callMe() {
writeln("The dependency was called.");
}
}
class AClass
{
class AClass {
@Autowire public ADependency dependency; // Dependencies are autowired before the post-constructor is called.
@PostConstruct public void postConstructor()
{
@PostConstruct public void postConstructor() {
writeln("The class is created.");
if (dependency !is null)
{
if (dependency !is null) {
writeln("The dependency is autowired.");
}
else
{
} else {
writeln("The dependency was NOT autowired.");
}
}
@PreDestroy public void preDestructor()
{
@PreDestroy public void preDestructor() {
writeln("The class is no longer registered with the container.");
}
}
public void main()
{
public void main() {
auto container = new shared DependencyContainer();
container.register!(ADependency).onConstructed((Object obj) {
writeln("ADependency constructed");

View file

@ -9,50 +9,39 @@ import poodinis;
import std.stdio;
interface Engine
{
interface Engine {
public void engage();
}
class FuelEngine : Engine
{
public void engage()
{
class FuelEngine : Engine {
public void engage() {
writeln("VROOOOOOM!");
}
}
class ElectricEngine : Engine
{
public void engage()
{
class ElectricEngine : Engine {
public void engage() {
writeln("hummmmmmmm....");
}
}
class HybridCar
{
class HybridCar {
alias KilometersPerHour = int;
@Autowire!FuelEngine private Engine fuelEngine;
@Autowire!ElectricEngine private Engine electricEngine;
public void moveAtSpeed(KilometersPerHour speed)
{
if (speed <= 45)
{
public void moveAtSpeed(KilometersPerHour speed) {
if (speed <= 45) {
electricEngine.engage();
}
else
{
} else {
fuelEngine.engage();
}
}
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!HybridCar;

View file

@ -7,31 +7,25 @@
import poodinis;
class Driver
{
class Driver {
}
interface Database
{
interface Database {
}
class RelationalDatabase : Database
{
class RelationalDatabase : Database {
private Driver driver;
this(Driver driver)
{ // Automatically injected on creation by container
this(Driver driver) { // Automatically injected on creation by container
this.driver = driver;
}
}
class DataWriter
{
class DataWriter {
@Autowire private Database database; // Automatically injected when class is resolved
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!Driver;
dependencies.register!DataWriter;

View file

@ -7,28 +7,23 @@
import poodinis;
class Violin
{
class Violin {
}
interface InstrumentPlayer
{
interface InstrumentPlayer {
}
class ViolinPlayer : InstrumentPlayer
{
class ViolinPlayer : InstrumentPlayer {
// Autowired concrete types can be registered on resolve
@Autowire private Violin violin;
}
class Orchestra
{
class Orchestra {
// Autowired non-concrete types can be registered on resolved, given they have a qualifier.
@Autowire!ViolinPlayer private InstrumentPlayer violinPlayer;
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
/*

View file

@ -10,12 +10,9 @@ import poodinis;
import std.stdio;
import std.string;
class IntValueInjector : ValueInjector!int
{
int get(string key)
{
switch (key)
{
class IntValueInjector : ValueInjector!int {
int get(string key) {
switch (key) {
case "http.port":
return 8080;
case "http.keep_alive":
@ -26,12 +23,9 @@ class IntValueInjector : ValueInjector!int
}
}
class StringValueInjector : ValueInjector!string
{
string get(string key)
{
switch (key)
{
class StringValueInjector : ValueInjector!string {
string get(string key) {
switch (key) {
case "http.hostname":
return "acme.org";
default:
@ -40,8 +34,7 @@ class StringValueInjector : ValueInjector!string
}
}
class HttpServer
{
class HttpServer {
@Value("http.port")
private int port = 80;
@ -55,15 +48,13 @@ class HttpServer
@MandatoryValue("http.keep_alive")
private int keepAliveTime; // A ResolveException is thrown when the value is not available, default assignments are not used.
public void serve()
{
public void serve() {
writeln(format("Serving pages for %s:%s with max connection count of %s",
hostName, port, maxConnections));
}
}
void main()
{
void main() {
auto dependencies = new shared DependencyContainer();
dependencies.register!(ValueInjector!int, IntValueInjector);
dependencies.register!(ValueInjector!string, StringValueInjector);

View file

@ -20,25 +20,17 @@
module poodinis.altphobos;
template isFunction(X...)
{
static if (X.length == 1)
{
static if (is(typeof(&X[0]) U : U*) && is(U == function) || is(typeof(&X[0]) U == delegate))
{
template isFunction(X...) {
static if (X.length == 1) {
static if (is(typeof(&X[0]) U : U*) && is(U == function) || is(typeof(&X[0]) U == delegate)) {
// x is a (nested) function symbol.
enum isFunction = true;
}
else static if (is(X[0] T))
{
} else static if (is(X[0] T)) {
// x is a type. Take the type of it and examine.
enum isFunction = is(T == function);
}
else
} else
enum isFunction = false;
}
else
{
} else {
enum isFunction = false;
}
}

View file

@ -30,13 +30,11 @@ import std.string : format;
import std.traits : BaseClassesTuple, FieldNameTuple, fullyQualifiedName, hasUDA, isDynamicArray;
import std.range : ElementType;
debug
{
debug {
import std.stdio : writeln;
}
private struct UseMemberType
{
private struct UseMemberType {
}
/**
@ -72,8 +70,7 @@ private struct UseMemberType
* autowire member "fuelEngine" as if it's of type "FuelEngine". This means that the members of instance "fuelEngine"
* will also be autowired because the autowire mechanism knows that member "fuelEngine" is an instance of "FuelEngine"
*/
struct Autowire(QualifierType)
{
struct Autowire(QualifierType) {
QualifierType qualifier;
}
@ -82,8 +79,7 @@ struct Autowire(QualifierType)
* Optional dependencies will not lead to a resolveException when there is no type registered for them.
* The member will remain null.
*/
struct OptionalDependency
{
struct OptionalDependency {
}
/**
@ -99,14 +95,11 @@ struct OptionalDependency
*---
* antenna will always be assigned a new instance of class Antenna.
*/
struct AssignNewInstance
{
struct AssignNewInstance {
}
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress)
{
debug
{
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) {
debug {
writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress));
}
}
@ -120,65 +113,48 @@ private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAd
*
* See_Also: Autowire
*/
public void autowire(Type)(shared(DependencyContainer) container, Type instance)
{
debug (poodinisVerbose)
{
public void autowire(Type)(shared(DependencyContainer) container, Type instance) {
debug (poodinisVerbose) {
printDebugAutowiredInstance(typeid(Type), &instance);
}
// Recurse into base class if there are more between Type and Object in the hierarchy
static if (BaseClassesTuple!Type.length > 1)
{
static if (BaseClassesTuple!Type.length > 1) {
autowire!(BaseClassesTuple!Type[0])(container, instance);
}
foreach (index, name; FieldNameTuple!Type)
{
foreach (index, name; FieldNameTuple!Type) {
autowireMember!(name, index, Type)(container, instance);
}
}
private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType,
void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member)
{
debug
{
void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) {
debug {
writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType,
candidateInstanceAddress, instanceType, instanceAddress, member));
}
}
private void printDebugAutowiringArray(TypeInfo superTypeInfo,
TypeInfo instanceType, void* instanceAddress, string member)
{
debug
{
TypeInfo instanceType, void* instanceAddress, string member) {
debug {
writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s",
superTypeInfo, instanceType, instanceAddress, member));
}
}
private void autowireMember(string member, size_t memberIndex, Type)(
shared(DependencyContainer) container, Type instance)
{
foreach (attribute; __traits(getAttributes, Type.tupleof[memberIndex]))
{
static if (is(attribute == Autowire!T, T))
{
shared(DependencyContainer) container, Type instance) {
foreach (attribute; __traits(getAttributes, Type.tupleof[memberIndex])) {
static if (is(attribute == Autowire!T, T)) {
injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance);
}
else static if (__traits(isSame, attribute, Autowire))
{
} else static if (__traits(isSame, attribute, Autowire)) {
injectInstance!(member, memberIndex, UseMemberType)(container, instance);
}
else static if (is(typeof(attribute) == Value))
{
} else static if (is(typeof(attribute) == Value)) {
enum key = attribute.key;
injectValue!(member, memberIndex, key, false)(container, instance);
}
else static if (is(typeof(attribute) == MandatoryValue))
{
} else static if (is(typeof(attribute) == MandatoryValue)) {
enum key = attribute.key;
injectValue!(member, memberIndex, key, true)(container, instance);
}
@ -186,20 +162,15 @@ private void autowireMember(string member, size_t memberIndex, Type)(
}
private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(
shared(DependencyContainer) container, Type instance)
{
if (instance.tupleof[memberIndex] is null)
{
shared(DependencyContainer) container, Type instance) {
if (instance.tupleof[memberIndex] is null) {
alias MemberType = typeof(Type.tupleof[memberIndex]);
enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency);
static if (isDynamicArray!MemberType)
{
static if (isDynamicArray!MemberType) {
injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container,
instance);
}
else
{
} else {
injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container,
instance);
}
@ -207,107 +178,80 @@ private void injectInstance(string member, size_t memberIndex, QualifierType, Ty
}
private void injectMultipleInstances(string member, size_t memberIndex,
bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance)
{
bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance) {
alias MemberElementType = ElementType!MemberType;
static if (isOptional)
{
static if (isOptional) {
auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
}
else
{
} else {
auto instances = container.resolveAll!MemberElementType;
}
instance.tupleof[memberIndex] = instances;
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
}
}
private void injectSingleInstance(string member, size_t memberIndex,
bool isOptional, MemberType, QualifierType, Type)(
shared(DependencyContainer) container, Type instance)
{
debug (poodinisVerbose)
{
shared(DependencyContainer) container, Type instance) {
debug (poodinisVerbose) {
TypeInfo qualifiedInstanceType = typeid(MemberType);
}
enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance);
MemberType qualifiedInstance;
static if (!is(QualifierType == UseMemberType))
{
static if (!is(QualifierType == UseMemberType)) {
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType,
assignNewInstance, isOptional)(container);
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
qualifiedInstanceType = typeid(QualifierType);
}
}
else
{
} else {
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType,
assignNewInstance, isOptional)(container);
}
instance.tupleof[memberIndex] = qualifiedInstance;
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
printDebugAutowiringCandidate(qualifiedInstanceType,
&qualifiedInstance, typeid(Type), &instance, member);
}
}
private QualifierType createOrResolveInstance(MemberType, QualifierType,
bool createNew, bool isOptional)(shared(DependencyContainer) container)
{
static if (createNew)
{
bool createNew, bool isOptional)(shared(DependencyContainer) container) {
static if (createNew) {
auto instanceFactory = new InstanceFactory();
instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType),
CreatesSingleton.no);
return cast(MemberType) instanceFactory.getInstance();
}
else
{
static if (isOptional)
{
} else {
static if (isOptional) {
return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
}
else
{
} else {
return container.resolve!(MemberType, QualifierType);
}
}
}
private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(
shared(DependencyContainer) container, Type instance)
{
shared(DependencyContainer) container, Type instance) {
alias MemberType = typeof(Type.tupleof[memberIndex]);
try
{
try {
auto injector = container.resolve!(ValueInjector!MemberType);
instance.tupleof[memberIndex] = injector.get(key);
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
}
}
catch (ResolveException e)
{
} catch (ResolveException e) {
throw new ValueInjectionException(format(
"Could not inject value of type %s into %s.%s: value injector is missing for this type.",
typeid(MemberType), typeid(Type), member));
}
catch (ValueNotAvailableException e)
{
static if (mandatory)
{
} catch (ValueNotAvailableException e) {
static if (mandatory) {
throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s",
typeid(MemberType), typeid(Type), member), e);
}
@ -315,10 +259,8 @@ private void injectValue(string member, size_t memberIndex, string key, bool man
}
private void printDebugValueInjection(TypeInfo instanceType,
void* instanceAddress, string member, TypeInfo valueType, string key)
{
debug
{
void* instanceAddress, string member, TypeInfo valueType, string key) {
debug {
writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s",
key, valueType, instanceType, instanceAddress, member));
}
@ -330,24 +272,20 @@ private void printDebugValueInjection(TypeInfo instanceType,
* See_Also: DependencyContainer
* Deprecated: Using the global container is undesired. See DependencyContainer.getInstance().
*/
public deprecated void globalAutowire(Type)(Type instance)
{
public deprecated void globalAutowire(Type)(Type instance) {
DependencyContainer.getInstance().autowire(instance);
}
class AutowiredRegistration(RegistrationType : Object) : Registration
{
class AutowiredRegistration(RegistrationType : Object) : Registration {
private shared(DependencyContainer) container;
public this(TypeInfo registeredType, InstanceFactory instanceFactory,
shared(DependencyContainer) originatingContainer)
{
shared(DependencyContainer) originatingContainer) {
super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer);
}
public override Object getInstance(
InstantiationContext context = new AutowireInstantiationContext())
{
InstantiationContext context = new AutowireInstantiationContext()) {
enforce(!(originatingContainer is null),
"The registration's originating container is null. There is no way to resolve autowire dependencies.");
@ -355,8 +293,7 @@ class AutowiredRegistration(RegistrationType : Object) : Registration
AutowireInstantiationContext autowireContext = cast(AutowireInstantiationContext) context;
enforce(!(autowireContext is null), "Given instantiation context type could not be cast to an AutowireInstantiationContext. If you relied on using the default assigned context: make sure you're calling getInstance() on an instance of type AutowiredRegistration!");
if (autowireContext.autowireInstance)
{
if (autowireContext.autowireInstance) {
originatingContainer.autowire(instance);
}
@ -365,18 +302,14 @@ class AutowiredRegistration(RegistrationType : Object) : Registration
return instance;
}
private void delegate() getPreDestructor(RegistrationType instance)
{
private void delegate() getPreDestructor(RegistrationType instance) {
void delegate() preDestructor = null;
foreach (memberName; __traits(allMembers, RegistrationType))
{
foreach (overload; __traits(getOverloads, instance, memberName))
{
foreach (memberName; __traits(allMembers, RegistrationType)) {
foreach (overload; __traits(getOverloads, instance, memberName)) {
static if (__traits(compiles, __traits(getProtection, overload))
&& __traits(getProtection, overload) == "public"
&& isFunction!overload
&& hasUDA!(overload, PreDestroy))
{
&& hasUDA!(overload, PreDestroy)) {
preDestructor = &__traits(getMember, instance, memberName);
}
}
@ -386,7 +319,6 @@ class AutowiredRegistration(RegistrationType : Object) : Registration
}
}
class AutowireInstantiationContext : InstantiationContext
{
class AutowireInstantiationContext : InstantiationContext {
public bool autowireInstance = true;
}

View file

@ -26,23 +26,19 @@ import std.algorithm : canFind;
import std.traits : fullyQualifiedName, hasUDA, BaseTypeTuple;
import std.meta : AliasSeq;
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
import std.stdio : writeln;
}
/**
* Exception thrown when errors occur while resolving a type in a dependency container.
*/
class ResolveException : Exception
{
this(string message, TypeInfo resolveType)
{
class ResolveException : Exception {
this(string message, TypeInfo resolveType) {
super(format("Exception while resolving type %s: %s", resolveType.toString(), message));
}
this(Throwable cause, TypeInfo resolveType)
{
this(Throwable cause, TypeInfo resolveType) {
super(format("Exception while resolving type %s", resolveType.toString()), cause);
}
}
@ -50,10 +46,8 @@ class ResolveException : Exception
/**
* Exception thrown when errors occur while registering a type in a dependency container.
*/
class RegistrationException : Exception
{
this(string message, TypeInfo registrationType)
{
class RegistrationException : Exception {
this(string message, TypeInfo registrationType) {
super(format("Exception while registering type %s: %s",
registrationType.toString(), message));
}
@ -62,8 +56,7 @@ class RegistrationException : Exception
/**
* 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
@ -75,8 +68,7 @@ public enum RegistrationOption
/**
* 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.
@ -99,8 +91,7 @@ public enum ResolveOption
* Multiple methods can be marked and will all be called after construction. The order in which
* methods are called is undetermined. Methods should have the signature void(void).
*/
struct PostConstruct
{
struct PostConstruct {
}
/**
@ -110,8 +101,7 @@ struct PostConstruct
* This method is called when removeRegistration or clearAllRegistrations is called.
* It will also be called when the container's destructor is called.
*/
struct PreDestroy
{
struct PreDestroy {
}
/**
@ -124,8 +114,7 @@ struct PreDestroy
* In most cases you want to use a global singleton dependency container provided by getInstance() to manage all dependencies.
* You can still create new instances of this class for exceptional situations.
*/
synchronized class DependencyContainer
{
synchronized class DependencyContainer {
private Registration[][TypeInfo] registrations;
private Registration[] autowireStack;
@ -133,8 +122,7 @@ synchronized class DependencyContainer
private RegistrationOption persistentRegistrationOptions;
private ResolveOption persistentResolveOptions;
~this()
{
~this() {
clearAllRegistrations();
}
@ -158,8 +146,7 @@ synchronized class DependencyContainer
*
* See_Also: singleInstance, newInstance, existingInstance
*/
public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none)
{
public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) {
return register!(ConcreteType, ConcreteType)(options);
}
@ -182,20 +169,17 @@ synchronized class DependencyContainer
*/
public Registration register(SuperType, ConcreteType:
SuperType)(RegistrationOption options = RegistrationOption.none)
if (!is(ConcreteType == struct))
{
if (!is(ConcreteType == struct)) {
TypeInfo registeredType = typeid(SuperType);
TypeInfo_Class concreteType = typeid(ConcreteType);
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
writeln(format("DEBUG: Register type %s (as %s)",
concreteType.toString(), registeredType.toString()));
}
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
if (existingRegistration)
{
if (existingRegistration) {
return existingRegistration;
}
@ -204,11 +188,9 @@ synchronized class DependencyContainer
instanceFactory, this);
newRegistration.initializeFactoryType().singleInstance();
static if (!is(SuperType == ConcreteType))
{
static if (!is(SuperType == ConcreteType)) {
if (!hasOption(options, persistentRegistrationOptions,
RegistrationOption.doNotAddConcreteTypeRegistration))
{
RegistrationOption.doNotAddConcreteTypeRegistration)) {
auto concreteTypeRegistration = register!ConcreteType;
concreteTypeRegistration.linkTo(newRegistration);
}
@ -219,38 +201,30 @@ synchronized class DependencyContainer
}
private bool hasOption(OptionType)(OptionType options,
OptionType persistentOptions, OptionType option)
{
OptionType persistentOptions, OptionType option) {
return ((options | persistentOptions) & option) != 0;
}
private OptionType buildFlags(OptionType)(OptionType[] options)
{
private OptionType buildFlags(OptionType)(OptionType[] options) {
OptionType flags;
foreach (option; options)
{
foreach (option; options) {
flags |= option;
}
return flags;
}
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType)
{
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) {
auto existingCandidates = registrationType in registrations;
if (existingCandidates)
{
if (existingCandidates) {
return getRegistration(cast(Registration[])*existingCandidates, qualifierType);
}
return null;
}
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType)
{
foreach (existingRegistration; candidates)
{
if (existingRegistration.instanceType == concreteType)
{
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) {
foreach (existingRegistration; candidates) {
if (existingRegistration.instanceType == concreteType) {
return existingRegistration;
}
}
@ -299,8 +273,7 @@ synchronized class DependencyContainer
*/
public RegistrationType resolve(RegistrationType)(
ResolveOption resolveOptions = ResolveOption.none)
if (!is(RegistrationType == struct))
{
if (!is(RegistrationType == struct)) {
return resolve!(RegistrationType, RegistrationType)(resolveOptions);
}
@ -332,32 +305,26 @@ synchronized class DependencyContainer
*/
public QualifierType resolve(RegistrationType, QualifierType:
RegistrationType)(ResolveOption resolveOptions = ResolveOption.none)
if (!is(QualifierType == struct))
{
if (!is(QualifierType == struct)) {
TypeInfo resolveType = typeid(RegistrationType);
TypeInfo qualifierType = typeid(QualifierType);
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString());
}
auto candidates = resolveType in registrations;
if (!candidates)
{
static if (is(typeof(typeid(QualifierType)) == TypeInfo_Class) && !__traits(isAbstractClass, QualifierType))
{
if (!candidates) {
static if (is(typeof(typeid(QualifierType)) == TypeInfo_Class) && !__traits(isAbstractClass, QualifierType)) {
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption
.registerBeforeResolving))
{
.registerBeforeResolving)) {
register!(RegistrationType, QualifierType)();
return resolve!(RegistrationType, QualifierType)(resolveOptions);
}
}
if (hasOption(resolveOptions, persistentResolveOptions,
ResolveOption.noResolveException))
{
ResolveOption.noResolveException)) {
return null;
}
@ -367,37 +334,29 @@ synchronized class DependencyContainer
Registration registration = getQualifiedRegistration(resolveType,
qualifierType, cast(Registration[])*candidates);
try
{
try {
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
callPostConstructors(newInstance);
return newInstance;
}
catch (ValueInjectionException e)
{
} catch (ValueInjectionException e) {
throw new ResolveException(e, resolveType);
}
}
bool isRegistered(RegistrationType)()
{
bool isRegistered(RegistrationType)() {
TypeInfo typeInfo = typeid(RegistrationType);
auto candidates = typeInfo in registrations;
return candidates !is null;
}
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration)
{
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
QualifierType instance;
if (!(cast(Registration[]) autowireStack).canFind(registration))
{
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
autowireStack ~= cast(shared(Registration)) registration;
instance = cast(QualifierType) registration.getInstance(
new AutowireInstantiationContext());
autowireStack = autowireStack[0 .. $ - 1];
}
else
{
} else {
auto autowireContext = new AutowireInstantiationContext();
autowireContext.autowireInstance = false;
instance = cast(QualifierType) registration.getInstance(autowireContext);
@ -423,25 +382,21 @@ synchronized class DependencyContainer
* ---
*/
public RegistrationType[] resolveAll(RegistrationType)(
ResolveOption resolveOptions = ResolveOption.none)
{
ResolveOption resolveOptions = ResolveOption.none) {
RegistrationType[] instances;
TypeInfo resolveType = typeid(RegistrationType);
auto qualifiedRegistrations = resolveType in registrations;
if (!qualifiedRegistrations)
{
if (!qualifiedRegistrations) {
if (hasOption(resolveOptions, persistentResolveOptions,
ResolveOption.noResolveException))
{
ResolveOption.noResolveException)) {
return [];
}
throw new ResolveException("Type not registered.", resolveType);
}
foreach (registration; cast(Registration[])*qualifiedRegistrations)
{
foreach (registration; cast(Registration[])*qualifiedRegistrations) {
instances ~= resolveAutowiredInstance!RegistrationType(registration);
}
@ -449,12 +404,9 @@ synchronized class DependencyContainer
}
private Registration getQualifiedRegistration(TypeInfo resolveType,
TypeInfo qualifierType, Registration[] candidates)
{
if (resolveType == qualifierType)
{
if (candidates.length > 1)
{
TypeInfo qualifierType, Registration[] candidates) {
if (resolveType == qualifierType) {
if (candidates.length > 1) {
string candidateList = candidates.toConcreteTypeListString();
throw new ResolveException(
"Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.",
@ -467,17 +419,13 @@ synchronized class DependencyContainer
return getRegistration(candidates, qualifierType);
}
private void callPostConstructors(Type)(Type instance)
{
foreach (memberName; __traits(allMembers, Type))
{
foreach (overload; __traits(getOverloads, instance, memberName))
{
private void callPostConstructors(Type)(Type instance) {
foreach (memberName; __traits(allMembers, Type)) {
foreach (overload; __traits(getOverloads, instance, memberName)) {
static if (__traits(compiles, __traits(getProtection, overload))
&& __traits(getProtection, overload) == "public"
&& isFunction!overload
&& hasUDA!(overload, PostConstruct))
{
&& hasUDA!(overload, PostConstruct)) {
__traits(getMember, instance, memberName)();
}
}
@ -487,10 +435,8 @@ synchronized class DependencyContainer
/**
* Clears all dependency registrations managed by this container.
*/
public void clearAllRegistrations()
{
foreach (registrationsOfType; registrations)
{
public void clearAllRegistrations() {
foreach (registrationsOfType; registrations) {
callPreDestructorsOfRegistrations(registrationsOfType);
}
registrations.destroy();
@ -506,20 +452,16 @@ synchronized class DependencyContainer
* container.removeRegistration!Animal;
* ---
*/
public void removeRegistration(RegistrationType)()
{
public void removeRegistration(RegistrationType)() {
auto registrationsOfType = *(typeid(RegistrationType) in registrations);
callPreDestructorsOfRegistrations(registrationsOfType);
registrations.remove(typeid(RegistrationType));
}
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations)
{
foreach (registration; registrations)
{
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) {
foreach (registration; registrations) {
Registration unsharedRegistration = cast(Registration) registration;
if (unsharedRegistration.preDestructor !is null)
{
if (unsharedRegistration.preDestructor !is null) {
unsharedRegistration.preDestructor()();
}
}
@ -528,32 +470,28 @@ synchronized class DependencyContainer
/**
* Apply persistent registration options which will be used everytime register() is called.
*/
public void setPersistentRegistrationOptions(RegistrationOption options)
{
public void setPersistentRegistrationOptions(RegistrationOption options) {
persistentRegistrationOptions = options;
}
/**
* Unsets all applied persistent registration options
*/
public void unsetPersistentRegistrationOptions()
{
public void unsetPersistentRegistrationOptions() {
persistentRegistrationOptions = RegistrationOption.none;
}
/**
* Apply persistent resolve options which will be used everytime resolve() is called.
*/
public void setPersistentResolveOptions(ResolveOption options)
{
public void setPersistentResolveOptions(ResolveOption options) {
persistentResolveOptions = options;
}
/**
* Unsets all applied persistent resolve options
*/
public void unsetPersistentResolveOptions()
{
public void unsetPersistentResolveOptions() {
persistentResolveOptions = ResolveOption.none;
}

View file

@ -20,10 +20,8 @@ import poodinis.autowire : autowire;
import std.traits : hasUDA, ReturnType;
class ApplicationContext
{
public void registerDependencies(shared(DependencyContainer) container)
{
class ApplicationContext {
public void registerDependencies(shared(DependencyContainer) container) {
}
}
@ -31,16 +29,14 @@ class ApplicationContext
* A component annotation is used for specifying which factory methods produce components in
* an application context.
*/
struct Component
{
struct Component {
}
/**
* This annotation allows you to specify by which super type the component should be registered. This
* enables you to use type-qualified alternatives for dependencies.
*/
struct RegisterByType(Type)
{
struct RegisterByType(Type) {
Type type;
}
@ -48,8 +44,7 @@ struct RegisterByType(Type)
* Components with the prototype registration will be scoped as dependencies which will create
* new instances every time they are resolved. The factory method will be called repeatedly.
*/
struct Prototype
{
struct Prototype {
}
/**
@ -59,8 +54,7 @@ struct Prototype
* It is mostly used for dependencies which come from an external library or when you don't
* want to use annotations to set-up dependencies in your classes.
*/
public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container)
{
public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) {
auto context = new Context();
context.registerDependencies(container);
context.registerContextComponents(container);
@ -69,33 +63,24 @@ public void registerContext(Context : ApplicationContext)(shared(DependencyConta
}
public void registerContextComponents(ApplicationContextType : ApplicationContext)(
ApplicationContextType context, shared(DependencyContainer) container)
{
foreach (memberName; __traits(allMembers, ApplicationContextType))
{
foreach (overload; __traits(getOverloads, context, memberName))
{
static if (__traits(getProtection, overload) == "public" && hasUDA!(overload, Component))
{
ApplicationContextType context, shared(DependencyContainer) container) {
foreach (memberName; __traits(allMembers, ApplicationContextType)) {
foreach (overload; __traits(getOverloads, context, memberName)) {
static if (__traits(getProtection, overload) == "public" && hasUDA!(overload, Component)) {
auto factoryMethod = &__traits(getMember, context, memberName);
Registration registration = null;
auto createsSingleton = CreatesSingleton.yes;
foreach (attribute; __traits(getAttributes, overload))
{
static if (is(attribute == RegisterByType!T, T))
{
foreach (attribute; __traits(getAttributes, overload)) {
static if (is(attribute == RegisterByType!T, T)) {
registration = container.register!(typeof(attribute.type),
ReturnType!factoryMethod);
}
else static if (__traits(isSame, attribute, Prototype))
{
} else static if (__traits(isSame, attribute, Prototype)) {
createsSingleton = CreatesSingleton.no;
}
}
if (registration is null)
{
if (registration is null) {
registration = container.register!(ReturnType!factoryMethod);
}

View file

@ -19,8 +19,7 @@ import std.exception : enforce;
import std.traits : Parameters, isBuiltinType, fullyQualifiedName;
import std.string : format;
debug
{
debug {
import std.stdio : writeln;
}
@ -28,42 +27,34 @@ alias CreatesSingleton = Flag!"CreatesSingleton";
alias InstanceFactoryMethod = Object delegate();
alias InstanceEventHandler = void delegate(Object instance);
class InstanceCreationException : Exception
{
this(string message, string file = __FILE__, size_t line = __LINE__)
{
class InstanceCreationException : Exception {
this(string message, string file = __FILE__, size_t line = __LINE__) {
super(message, file, line);
}
}
struct InstanceFactoryParameters
{
struct InstanceFactoryParameters {
TypeInfo_Class instanceType;
CreatesSingleton createsSingleton = CreatesSingleton.yes;
Object existingInstance;
InstanceFactoryMethod factoryMethod;
}
class InstanceFactory
{
class InstanceFactory {
private Object instance = null;
private InstanceFactoryParameters _factoryParameters;
private InstanceEventHandler _constructionHandler;
this()
{
this() {
factoryParameters = InstanceFactoryParameters();
}
public @property void factoryParameters(InstanceFactoryParameters factoryParameters)
{
if (factoryParameters.factoryMethod is null)
{
public @property void factoryParameters(InstanceFactoryParameters factoryParameters) {
if (factoryParameters.factoryMethod is null) {
factoryParameters.factoryMethod = &this.createInstance;
}
if (factoryParameters.existingInstance !is null)
{
if (factoryParameters.existingInstance !is null) {
factoryParameters.createsSingleton = CreatesSingleton.yes;
this.instance = factoryParameters.existingInstance;
}
@ -71,99 +62,76 @@ class InstanceFactory
_factoryParameters = factoryParameters;
}
public @property InstanceFactoryParameters factoryParameters()
{
public @property InstanceFactoryParameters factoryParameters() {
return _factoryParameters;
}
public Object getInstance()
{
if (_factoryParameters.createsSingleton && instance !is null)
{
debug (poodinisVerbose)
{
public Object getInstance() {
if (_factoryParameters.createsSingleton && instance !is null) {
debug (poodinisVerbose) {
printDebugUseExistingInstance();
}
return instance;
}
debug (poodinisVerbose)
{
debug (poodinisVerbose) {
printDebugCreateNewInstance();
}
instance = _factoryParameters.factoryMethod();
if (_constructionHandler !is null)
{
if (_constructionHandler !is null) {
_constructionHandler(instance);
}
return instance;
}
void onConstructed(InstanceEventHandler handler)
{
void onConstructed(InstanceEventHandler handler) {
_constructionHandler = handler;
}
private void printDebugUseExistingInstance()
{
debug
{
if (_factoryParameters.instanceType !is null)
{
private void printDebugUseExistingInstance() {
debug {
if (_factoryParameters.instanceType !is null) {
writeln(format("DEBUG: Existing instance returned of type %s",
_factoryParameters.instanceType.toString()));
}
else
{
} else {
writeln("DEBUG: Existing instance returned from custom factory method");
}
}
}
private void printDebugCreateNewInstance()
{
debug
{
if (_factoryParameters.instanceType !is null)
{
private void printDebugCreateNewInstance() {
debug {
if (_factoryParameters.instanceType !is null) {
writeln(format("DEBUG: Creating new instance of type %s",
_factoryParameters.instanceType.toString()));
}
else
{
} else {
writeln("DEBUG: Creating new instance from custom factory method");
}
}
}
protected Object createInstance()
{
protected Object createInstance() {
enforce!InstanceCreationException(_factoryParameters.instanceType,
"Instance type is not defined, cannot create instance without knowing its type.");
return _factoryParameters.instanceType.create();
}
}
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
{
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
private shared DependencyContainer container;
private bool isBeingInjected = false;
this(shared DependencyContainer container)
{
this(shared DependencyContainer container) {
this.container = container;
}
private static string createArgumentList(Params...)()
{
private static string createArgumentList(Params...)() {
string argumentList = "";
foreach (param; Params)
{
if (argumentList.length > 0)
{
foreach (param; Params) {
if (argumentList.length > 0) {
argumentList ~= ",";
}
@ -172,23 +140,18 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
return argumentList;
}
private static string createImportList(Params...)()
{
private static string createImportList(Params...)() {
string importList = "";
foreach (param; Params)
{
foreach (param; Params) {
importList ~= createImportsString!param;
}
return importList;
}
private static bool parametersAreValid(Params...)()
{
private static bool parametersAreValid(Params...)() {
bool isValid = true;
foreach (param; Params)
{
if (isBuiltinType!param || is(param == struct))
{
foreach (param; Params) {
if (isBuiltinType!param || is(param == struct)) {
isValid = false;
break;
}
@ -197,8 +160,7 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
return isValid;
}
protected override Object createInstance()
{
protected override Object createInstance() {
enforce!InstanceCreationException(container,
"A dependency container is not defined. Cannot perform constructor injection without one.");
enforce!InstanceCreationException(!isBeingInjected,
@ -206,16 +168,14 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
InstanceType.stringof));
Object instance = null;
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`)))
{
foreach (ctor; __traits(getOverloads, InstanceType, `__ctor`))
{
static if (parametersAreValid!(Parameters!ctor))
{
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
foreach (ctor; __traits(getOverloads, InstanceType, `__ctor`)) {
static if (parametersAreValid!(Parameters!ctor)) {
isBeingInjected = true;
mixin(createImportsString!InstanceType ~ createImportList!(
Parameters!ctor) ~ `
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(
instance = new `
~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(
Parameters!ctor) ~ `);
`);
isBeingInjected = false;
@ -224,8 +184,7 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
}
}
if (instance is null)
{
if (instance is null) {
instance = typeid(InstanceType).create();
}

View file

@ -14,16 +14,12 @@ module poodinis.imports;
import std.meta : staticIndexOf;
import std.traits : moduleName, TemplateArgsOf, isBuiltinType, isType;
public static string createImportsString(Type, ParentTypeList...)()
{
public static string createImportsString(Type, ParentTypeList...)() {
string imports = `import ` ~ moduleName!Type ~ `;`;
static if (__traits(compiles, TemplateArgsOf!Type))
{
foreach (TemplateArgType; TemplateArgsOf!Type)
{
static if (__traits(compiles, TemplateArgsOf!Type)) {
foreach (TemplateArgType; TemplateArgsOf!Type) {
static if (isType!TemplateArgType &&
(!isBuiltinType!TemplateArgType && staticIndexOf!(TemplateArgType, ParentTypeList) == -1))
{
(!isBuiltinType!TemplateArgType && staticIndexOf!(TemplateArgType, ParentTypeList) == -1)) {
imports ~= createImportsString!(TemplateArgType, ParentTypeList, Type);
}
}

View file

@ -27,10 +27,8 @@ module poodinis.polyfill;
import std.exception;
static if (!__traits(compiles, basicExceptionCtors))
{
mixin template basicExceptionCtors()
{
static if (!__traits(compiles, basicExceptionCtors)) {
mixin template basicExceptionCtors() {
/++
Params:
msg = The message for the exception.
@ -38,8 +36,7 @@ static if (!__traits(compiles, basicExceptionCtors))
line = The line number where the exception occurred.
next = The previous exception in the chain of exceptions, if any.
+/
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @nogc @safe pure nothrow
{
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @nogc @safe pure nothrow {
super(msg, file, line, next);
}
@ -50,13 +47,10 @@ static if (!__traits(compiles, basicExceptionCtors))
file = The file where the exception occurred.
line = The line number where the exception occurred.
+/
this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @nogc @safe pure nothrow
{
this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @nogc @safe pure nothrow {
super(msg, file, line, next);
}
}
}
else
{
} else {
public import std.exception : basicExceptionCtors;
}

View file

@ -17,8 +17,7 @@ import poodinis.container : DependencyContainer;
import poodinis.factory : InstanceFactory, InstanceEventHandler,
InstanceCreationException, InstanceFactoryParameters, CreatesSingleton;
class Registration
{
class Registration {
private TypeInfo _registeredType = null;
private TypeInfo_Class _instanceType = null;
private Registration linkedRegistration;
@ -26,54 +25,44 @@ class Registration
private InstanceFactory _instanceFactory;
private void delegate() _preDestructor;
public @property registeredType()
{
public @property registeredType() {
return _registeredType;
}
public @property instanceType()
{
public @property instanceType() {
return _instanceType;
}
public @property originatingContainer()
{
public @property originatingContainer() {
return _originatingContainer;
}
public @property instanceFactory()
{
public @property instanceFactory() {
return _instanceFactory;
}
public @property preDestructor()
{
public @property preDestructor() {
return _preDestructor;
}
protected @property preDestructor(void delegate() preDestructor)
{
protected @property preDestructor(void delegate() preDestructor) {
_preDestructor = preDestructor;
}
this(TypeInfo registeredType, TypeInfo_Class instanceType,
InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer)
{
InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
this._registeredType = registeredType;
this._instanceType = instanceType;
this._originatingContainer = originatingContainer;
this._instanceFactory = instanceFactory;
}
public Object getInstance(InstantiationContext context = new InstantiationContext())
{
if (linkedRegistration !is null)
{
public Object getInstance(InstantiationContext context = new InstantiationContext()) {
if (linkedRegistration !is null) {
return linkedRegistration.getInstance(context);
}
if (instanceFactory is null)
{
if (instanceFactory is null) {
throw new InstanceCreationException(
"No instance factory defined for registration of type " ~ registeredType.toString());
}
@ -81,27 +70,23 @@ class Registration
return instanceFactory.getInstance();
}
public Registration linkTo(Registration registration)
{
public Registration linkTo(Registration registration) {
this.linkedRegistration = registration;
return this;
}
Registration onConstructed(InstanceEventHandler handler)
{
Registration onConstructed(InstanceEventHandler handler) {
if (instanceFactory !is null)
instanceFactory.onConstructed(handler);
return this;
}
}
private InstanceFactoryParameters copyFactoryParameters(Registration registration)
{
private InstanceFactoryParameters copyFactoryParameters(Registration registration) {
return registration.instanceFactory.factoryParameters;
}
private void setFactoryParameters(Registration registration, InstanceFactoryParameters newParameters)
{
private void setFactoryParameters(Registration registration, InstanceFactoryParameters newParameters) {
registration.instanceFactory.factoryParameters = newParameters;
}
@ -110,8 +95,7 @@ private void setFactoryParameters(Registration registration, InstanceFactoryPara
*
* This is not a registration scope. Typically used by Poodinis internally only.
*/
public Registration initializeFactoryType(Registration registration)
{
public Registration initializeFactoryType(Registration registration) {
auto params = registration.copyFactoryParameters();
params.instanceType = registration.instanceType;
registration.setFactoryParameters(params);
@ -123,8 +107,7 @@ public Registration initializeFactoryType(Registration registration)
*
* Effectively makes the given registration a singleton.
*/
public Registration singleInstance(Registration registration)
{
public Registration singleInstance(Registration registration) {
auto params = registration.copyFactoryParameters();
params.createsSingleton = CreatesSingleton.yes;
registration.setFactoryParameters(params);
@ -134,8 +117,7 @@ public Registration singleInstance(Registration registration)
/**
* Scopes registrations to return a new instance every time the given registration is resolved.
*/
public Registration newInstance(Registration registration)
{
public Registration newInstance(Registration registration) {
auto params = registration.copyFactoryParameters();
params.createsSingleton = CreatesSingleton.no;
params.existingInstance = null;
@ -146,8 +128,7 @@ public Registration newInstance(Registration registration)
/**
* Scopes registrations to return the given instance every time the given registration is resolved.
*/
public Registration existingInstance(Registration registration, Object instance)
{
public Registration existingInstance(Registration registration, Object instance) {
auto params = registration.copyFactoryParameters();
params.createsSingleton = CreatesSingleton.yes;
params.existingInstance = instance;
@ -159,8 +140,7 @@ public Registration existingInstance(Registration registration, Object instance)
* Scopes registrations to create new instances using the given initializer delegate.
*/
public Registration initializedBy(T)(Registration registration, T delegate() initializer)
if (is(T == class) || is(T == interface))
{
if (is(T == class) || is(T == interface)) {
auto params = registration.copyFactoryParameters();
params.createsSingleton = CreatesSingleton.no;
params.factoryMethod = () => cast(Object) initializer();
@ -171,8 +151,7 @@ public Registration initializedBy(T)(Registration registration, T delegate() ini
/**
* Scopes registrations to create a new instance using the given initializer delegate. On subsequent resolves the same instance is returned.
*/
public Registration initializedOnceBy(T : Object)(Registration registration, T delegate() initializer)
{
public Registration initializedOnceBy(T : Object)(Registration registration, T delegate() initializer) {
auto params = registration.copyFactoryParameters();
params.createsSingleton = CreatesSingleton.yes;
params.factoryMethod = () => cast(Object) initializer();
@ -180,13 +159,10 @@ public Registration initializedOnceBy(T : Object)(Registration registration, T d
return registration;
}
public string toConcreteTypeListString(Registration[] registrations)
{
public string toConcreteTypeListString(Registration[] registrations) {
auto concreteTypeListString = "";
foreach (registration; registrations)
{
if (concreteTypeListString.length > 0)
{
foreach (registration; registrations) {
if (concreteTypeListString.length > 0) {
concreteTypeListString ~= ", ";
}
concreteTypeListString ~= registration.instanceType.toString();
@ -194,6 +170,5 @@ public string toConcreteTypeListString(Registration[] registrations)
return concreteTypeListString;
}
class InstantiationContext
{
class InstantiationContext {
}

View file

@ -18,23 +18,19 @@ import std.string : format;
/**
* Thrown when something goes wrong during value injection.
*/
class ValueInjectionException : Exception
{
class ValueInjectionException : Exception {
mixin basicExceptionCtors;
}
/**
* Thrown by injectors when the value with the given key cannot be found.
*/
class ValueNotAvailableException : Exception
{
this(string key)
{
class ValueNotAvailableException : Exception {
this(string key) {
super(format("Value for key %s is not available", key));
}
this(string key, Throwable cause)
{
this(string key, Throwable cause) {
super(format("Value for key %s is not available", key), cause);
}
}
@ -56,8 +52,7 @@ class ValueNotAvailableException : Exception
* }
* ---
*/
struct Value
{
struct Value {
/**
* The textual key used to find the value by injectors.
*
@ -83,8 +78,7 @@ struct Value
* }
* ---
*/
struct MandatoryValue
{
struct MandatoryValue {
/**
* The textual key used to find the value by injectors.
*
@ -115,8 +109,7 @@ struct MandatoryValue
* container.register!(ValueInjector!int, MyIntInjector);
* ---
*/
interface ValueInjector(Type)
{
interface ValueInjector(Type) {
/**
* Get a value from the injector by key.
*

View file

@ -10,12 +10,10 @@ import poodinis.test.testclasses;
import std.exception;
version (unittest)
{
version (unittest) {
// Test autowiring concrete type to existing instance
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentA;
auto componentB = new ComponentB();
@ -24,8 +22,7 @@ version (unittest)
}
// Test autowiring interface type to existing instance
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC);
auto componentD = new ComponentD();
@ -34,8 +31,7 @@ version (unittest)
}
// Test autowiring private members
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC);
auto componentD = new ComponentD();
@ -45,8 +41,7 @@ version (unittest)
}
// Test autowiring will only happen once
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC).newInstance();
auto componentD = new ComponentD();
@ -59,8 +54,7 @@ version (unittest)
}
// Test autowiring unregistered type
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto componentD = new ComponentD();
assertThrown!(ResolveException)(container.autowire(componentD),
@ -68,8 +62,7 @@ version (unittest)
}
// Test autowiring member with non-autowire attribute does not autowire
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto componentE = new ComponentE();
container.autowire(componentE);
@ -78,8 +71,7 @@ version (unittest)
}
// Test autowire class with alias declaration
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentA;
auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
@ -91,8 +83,7 @@ version (unittest)
}
// Test autowire class with qualifier
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX);
@ -105,8 +96,7 @@ version (unittest)
}
// Test autowire class with multiple qualifiers
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX);
@ -123,8 +113,7 @@ version (unittest)
}
// Test getting instance from autowired registration will autowire instance
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentA;
@ -137,8 +126,7 @@ version (unittest)
}
// Test autowiring a dynamic array with all qualified types
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX);
@ -150,8 +138,7 @@ version (unittest)
}
// Test autowiring new instance of singleinstance registration with newInstance UDA
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentA;
@ -165,8 +152,7 @@ version (unittest)
}
// Test autowiring members from base class
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentA;
container.register!ComponentB;
@ -179,8 +165,7 @@ version (unittest)
}
// Test autowiring optional dependencies
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto instance = new OuttaTime();
@ -192,8 +177,7 @@ version (unittest)
}
// Test autowiring class using value injection
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(ValueInjector!int, TestInjector);
@ -207,8 +191,7 @@ version (unittest)
}
// Test autowiring classes with recursive template parameters
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!CircularTemplateComponentA;
container.register!CircularTemplateComponentB;
@ -224,8 +207,7 @@ version (unittest)
}
// Test autowiring class where a method is marked with @Autowire does nothing
unittest
{
unittest {
// It should also not show deprecation warning:
// Deprecation: `__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `lala`
// the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from

View file

@ -12,12 +12,10 @@ import poodinis.test.foreigndependencies;
import std.exception;
import core.thread;
version (unittest)
{
version (unittest) {
// Test register concrete type
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto registration = container.register!TestClass;
assert(registration.registeredType == typeid(TestClass),
@ -25,8 +23,7 @@ version (unittest)
}
// Test resolve registered type
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass;
TestClass actualInstance = container.resolve!TestClass;
@ -35,8 +32,7 @@ version (unittest)
}
// Test register interface
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(TestInterface, TestClass);
TestInterface actualInstance = container.resolve!TestInterface;
@ -46,16 +42,14 @@ version (unittest)
}
// Test resolve non-registered type
unittest
{
unittest {
auto container = new shared DependencyContainer();
assertThrown!ResolveException(container.resolve!TestClass,
"Resolving non-registered type does not fail");
}
// Test clear registrations
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass;
container.clearAllRegistrations();
@ -64,8 +58,7 @@ version (unittest)
}
// Test resolve single instance for type
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass.singleInstance();
auto instance1 = container.resolve!TestClass;
@ -75,8 +68,7 @@ version (unittest)
}
// Test resolve new instance for type
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass.newInstance();
auto instance1 = container.resolve!TestClass;
@ -86,8 +78,7 @@ version (unittest)
}
// Test resolve existing instance for type
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto expectedInstance = new TestClass();
container.register!TestClass.existingInstance(expectedInstance);
@ -97,8 +88,7 @@ version (unittest)
}
// Test creating instance via custom initializer on resolve
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto expectedInstance = new TestClass();
container.register!TestClass.initializedBy({ return expectedInstance; });
@ -108,8 +98,7 @@ version (unittest)
}
// Test creating instance via initializedBy creates new instance every time
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass.initializedBy({ return new TestClass(); });
auto firstInstance = container.resolve!TestClass;
@ -118,8 +107,7 @@ version (unittest)
}
// Test creating instance via initializedOnceBy creates a singleton instance
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass.initializedOnceBy({ return new TestClass(); });
auto firstInstance = container.resolve!TestClass;
@ -128,8 +116,7 @@ version (unittest)
}
// Test autowire resolved instances
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!AutowiredClass;
container.register!ComponentClass;
@ -140,8 +127,7 @@ version (unittest)
}
// Test circular autowiring
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ComponentMouse;
container.register!ComponentCat;
@ -152,8 +138,7 @@ version (unittest)
}
// Test remove registration
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass;
container.removeRegistration!TestClass;
@ -161,8 +146,7 @@ version (unittest)
}
// Test autowiring does not autowire member where instance is non-null
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto existingA = new AutowiredClass();
auto existingB = new ComponentClass();
@ -178,8 +162,7 @@ version (unittest)
}
// Test autowiring circular dependency by third-degree
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Eenie;
container.register!Meenie;
@ -192,8 +175,7 @@ version (unittest)
}
// Test autowiring deep circular dependencies
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Ittie;
container.register!Bittie;
@ -205,8 +187,7 @@ version (unittest)
}
// Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Ittie.newInstance();
container.register!Bittie.newInstance();
@ -219,8 +200,7 @@ version (unittest)
}
// Test autowiring type registered by interface
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Bunena;
container.register!Bittie;
@ -234,17 +214,13 @@ version (unittest)
}
// Test reusing a container after clearing all registrations
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Banana;
container.clearAllRegistrations();
try
{
try {
container.resolve!Banana;
}
catch (ResolveException e)
{
} catch (ResolveException e) {
container.register!Banana;
return;
}
@ -252,16 +228,14 @@ version (unittest)
}
// Test register multiple concrete classess to same interface type
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Color, Blue);
container.register!(Color, Red);
}
// Test removing all registrations for type with multiple registrations.
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Color, Blue);
container.register!(Color, Red);
@ -269,8 +243,7 @@ version (unittest)
}
// Test registering same registration again
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto firstRegistration = container.register!(Color, Blue);
auto secondRegistration = container.register!(Color, Blue);
@ -280,25 +253,20 @@ version (unittest)
}
// Test resolve registration with multiple qualifiers
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Color, Blue);
container.register!(Color, Red);
try
{
try {
container.resolve!Color;
}
catch (ResolveException e)
{
} catch (ResolveException e) {
return;
}
assert(false);
}
// Test resolve registration with multiple qualifiers using a qualifier
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Color, Blue);
container.register!(Color, Red);
@ -312,8 +280,7 @@ version (unittest)
}
// Test autowire of unqualified member typed by interface.
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Spiders;
container.register!(TestInterface, TestClass);
@ -324,8 +291,7 @@ version (unittest)
}
// Register existing registration
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto firstRegistration = container.register!TestClass;
@ -336,8 +302,7 @@ version (unittest)
}
// Register existing registration by supertype
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto firstRegistration = container.register!(TestInterface, TestClass);
@ -348,8 +313,7 @@ version (unittest)
}
// Resolve dependency depending on itself
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Recursive;
@ -361,8 +325,7 @@ version (unittest)
}
// Test autowire stack pop-back
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Moolah;
container.register!Wants.newInstance();
@ -375,8 +338,7 @@ version (unittest)
}
// Test resolving registration registered in different thread
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto thread = new Thread(delegate() { container.register!TestClass; });
@ -387,8 +349,7 @@ version (unittest)
}
// Test resolving instance previously resolved in different thread
unittest
{
unittest {
auto container = new shared DependencyContainer();
shared(TestClass) actualTestClass;
@ -407,8 +368,7 @@ version (unittest)
}
// Test registering type with option doNotAddConcreteTypeRegistration
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(TestInterface,
TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration);
@ -418,16 +378,14 @@ version (unittest)
}
// Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration);
container.resolve!TestClass;
}
// Test registering type will register by contrete type by default
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(TestInterface, TestClass);
@ -438,8 +396,7 @@ version (unittest)
}
// Test resolving all registrations to an interface
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Color, Blue);
container.register!(Color, Red);
@ -450,8 +407,7 @@ version (unittest)
}
// Test autowiring instances resolved in array
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!UnrelatedClass;
container.register!(TestInterface, TestClassDeux);
@ -463,8 +419,7 @@ version (unittest)
}
// Test set persistent registration options
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.setPersistentRegistrationOptions(
RegistrationOption.doNotAddConcreteTypeRegistration);
@ -473,8 +428,7 @@ version (unittest)
}
// Test unset persistent registration options
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.setPersistentRegistrationOptions(
RegistrationOption.doNotAddConcreteTypeRegistration);
@ -484,24 +438,21 @@ version (unittest)
}
// Test registration when resolving
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving);
container.resolve!TestClass;
}
// Test set persistent resolve options
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
container.resolve!TestClass;
}
// Test unset persistent resolve options
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
container.unsetPersistentResolveOptions();
@ -509,32 +460,28 @@ version (unittest)
}
// Test ResolveOption registerBeforeResolving fails for interfaces
unittest
{
unittest {
auto container = new shared DependencyContainer();
assertThrown!ResolveException(
container.resolve!TestInterface(ResolveOption.registerBeforeResolving));
}
// Test ResolveOption noResolveException does not throw
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto instance = container.resolve!TestInterface(ResolveOption.noResolveException);
assert(instance is null);
}
// ResolveOption noResolveException does not throw for resolveAll
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException);
assert(instances.length == 0);
}
// Test autowired, constructor injected class
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Red;
container.register!Moolah;
@ -548,8 +495,7 @@ version (unittest)
}
// Test autowired, constructor injected class where constructor argument is templated
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!PieChart;
container.register!(TemplatedComponent!PieChart);
@ -562,8 +508,7 @@ version (unittest)
}
// Test injecting constructor with super-type parameter
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Wallpaper;
container.register!(Color, Blue);
@ -574,8 +519,7 @@ version (unittest)
}
// Test prevention of circular dependencies during constructor injection
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Pot;
container.register!Kettle;
@ -584,8 +528,7 @@ version (unittest)
}
// Test prevention of transitive circular dependencies during constructor injection
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Rock;
container.register!Paper;
@ -595,8 +538,7 @@ version (unittest)
}
// Test injection of foreign dependency in constructor
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Ola;
container.register!Hello;
@ -604,8 +546,7 @@ version (unittest)
}
// Test PostConstruct method is called after resolving a dependency
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!PostConstructionDependency;
@ -614,8 +555,7 @@ version (unittest)
}
// Test PostConstruct of base type is called
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ChildOfPostConstruction;
@ -624,8 +564,7 @@ version (unittest)
}
// Test PostConstruct of class implementing interface is not called
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ButThereWontBe;
@ -634,8 +573,7 @@ version (unittest)
}
// Test postconstruction happens after autowiring and value injection
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(ValueInjector!int, PostConstructingIntInjector);
container.register!PostConstructionDependency;
@ -644,8 +582,7 @@ version (unittest)
}
// Test PreDestroy is called when removing a registration
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!PreDestroyerOfFates;
auto instance = container.resolve!PreDestroyerOfFates;
@ -654,8 +591,7 @@ version (unittest)
}
// Test PreDestroy is called when removing all registrations
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!PreDestroyerOfFates;
auto instance = container.resolve!PreDestroyerOfFates;
@ -664,8 +600,7 @@ version (unittest)
}
// Test PreDestroy is called when the container is destroyed
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!PreDestroyerOfFates;
auto instance = container.resolve!PreDestroyerOfFates;
@ -675,8 +610,7 @@ version (unittest)
}
// Test register class by ancestor type
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(Grandma, Kid);
auto instance = container.resolve!Grandma;

View file

@ -10,12 +10,10 @@ import poodinis.test.testclasses;
import std.exception;
version (unittest)
{
version (unittest) {
//Test register component registrations from context
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto context = new TestContext();
context.registerContextComponents(container);
@ -25,8 +23,7 @@ version (unittest)
}
//Test non-annotated methods are not registered
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto context = new TestContext();
context.registerContextComponents(container);
@ -34,8 +31,7 @@ version (unittest)
}
//Test register component by base type
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto context = new TestContext();
context.registerContextComponents(container);
@ -44,8 +40,7 @@ version (unittest)
}
//Test register components with multiple candidates
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto context = new TestContext();
context.registerContextComponents(container);
@ -58,8 +53,7 @@ version (unittest)
}
//Test register component as prototype
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto context = new TestContext();
context.registerContextComponents(container);
@ -72,8 +66,7 @@ version (unittest)
}
// Test setting up simple dependencies through application context
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.registerContext!SimpleContext;
auto instance = container.resolve!CakeChart;
@ -82,8 +75,7 @@ version (unittest)
}
// Test resolving dependency from registered application context
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.registerContext!SimpleContext;
auto instance = container.resolve!Apple;
@ -92,8 +84,7 @@ version (unittest)
}
// Test autowiring application context
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!Apple;
container.registerContext!AutowiredTestContext;
@ -104,8 +95,7 @@ version (unittest)
}
// Test autowiring application context with dependencies registered in same context
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.registerContext!ComplexAutowiredTestContext;
auto instance = container.resolve!ClassWrapperWrapper;
@ -118,8 +108,7 @@ version (unittest)
}
// Test resolving registered context
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.registerContext!TestContext;
container.resolve!ApplicationContext;

View file

@ -10,12 +10,10 @@ import poodinis.test.testclasses;
import std.exception;
version (unittest)
{
version (unittest) {
// Test instance factory with singletons
unittest
{
unittest {
auto factory = new InstanceFactory();
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
CreatesSingleton.yes);
@ -27,8 +25,7 @@ version (unittest)
}
// Test instance factory with new instances
unittest
{
unittest {
auto factory = new InstanceFactory();
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
CreatesSingleton.no);
@ -40,8 +37,7 @@ version (unittest)
}
// Test instance factory with existing instances
unittest
{
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory();
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
@ -56,8 +52,7 @@ version (unittest)
}
// Test instance factory with existing instances when setting singleton flag to "no"
unittest
{
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory();
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
@ -69,10 +64,8 @@ version (unittest)
}
// Test creating instance using custom factory method
unittest
{
Object factoryMethod()
{
unittest {
Object factoryMethod() {
auto instance = new TestImplementation();
instance.someContent = "Ducks!";
return instance;
@ -89,8 +82,7 @@ version (unittest)
}
// Test injecting constructor of class
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!TestImplementation;
@ -102,8 +94,7 @@ version (unittest)
}
// Test injecting constructor of class with multiple constructors injects the first candidate
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!SomeOtherClassThen;
container.register!TestImplementation;
@ -118,8 +109,7 @@ version (unittest)
}
// Test injecting constructor of class with multiple constructor parameters
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!SomeOtherClassThen;
container.register!TestImplementation;
@ -134,8 +124,7 @@ version (unittest)
}
// Test injecting constructor of class with primitive constructor parameters
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!SomeOtherClassThen;
@ -148,8 +137,7 @@ version (unittest)
}
// Test injecting constructor of class with struct constructor parameters
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!SomeOtherClassThen;
@ -161,8 +149,7 @@ version (unittest)
}
// Test injecting constructor of class with empty constructor will skip injection
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container);
@ -173,8 +160,7 @@ version (unittest)
}
// Test injecting constructor of class with no candidates fails
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(

View file

@ -7,9 +7,7 @@
module poodinis.test.foreigndependencies;
version (unittest)
{
class Ola
{
version (unittest) {
class Ola {
}
}

View file

@ -10,19 +10,16 @@ import poodinis.test.testclasses;
import std.exception;
version (unittest)
{
version (unittest) {
// Test getting instance without scope defined throws exception
unittest
{
unittest {
Registration registration = new Registration(typeid(TestType), null, null, null);
assertThrown!(InstanceCreationException)(registration.getInstance(), null);
}
// Test set single instance scope using scope setter
unittest
{
unittest {
Registration registration = new Registration(null, typeid(TestType),
new InstanceFactory(), null).initializeFactoryType();
auto chainedRegistration = registration.singleInstance();
@ -35,8 +32,7 @@ version (unittest)
}
// Test set new instance scope using scope setter
unittest
{
unittest {
Registration registration = new Registration(null, typeid(TestType),
new InstanceFactory(), null).initializeFactoryType();
auto chainedRegistration = registration.newInstance();
@ -49,8 +45,7 @@ version (unittest)
}
// Test set existing instance scope using scope setter
unittest
{
unittest {
Registration registration = new Registration(null, null, new InstanceFactory(), null);
auto expectedInstance = new TestType();
auto chainedRegistration = registration.existingInstance(expectedInstance);
@ -62,8 +57,7 @@ version (unittest)
}
// Test linking registrations
unittest
{
unittest {
Registration firstRegistration = new Registration(typeid(TestInterface),
typeid(TestImplementation), new InstanceFactory(), null).initializeFactoryType()
.singleInstance();
@ -78,8 +72,7 @@ version (unittest)
}
// Test custom factory method via initializedBy
unittest
{
unittest {
Registration registration = new Registration(typeid(TestInterface),
typeid(TestImplementation), new InstanceFactory(), null);
@ -97,8 +90,7 @@ version (unittest)
}
// Test custom factory method via initializedOnceBy
unittest
{
unittest {
Registration registration = new Registration(typeid(TestInterface),
typeid(TestImplementation), new InstanceFactory(), null);
@ -116,8 +108,7 @@ version (unittest)
}
// Test chaining single/new instance scope to initializedBy will not overwrite the factory method.
unittest
{
unittest {
Registration registration = new Registration(typeid(TestInterface),
typeid(TestImplementation), new InstanceFactory(), null);

View file

@ -10,92 +10,73 @@ module poodinis.test.testclasses;
import poodinis;
import poodinis.test.foreigndependencies;
version (unittest)
{
class ComponentA
{
version (unittest) {
class ComponentA {
}
class ComponentB
{
class ComponentB {
public @Autowire ComponentA componentA;
}
interface InterfaceA
{
interface InterfaceA {
}
class ComponentC : InterfaceA
{
class ComponentC : InterfaceA {
}
class ComponentD
{
class ComponentD {
public @Autowire InterfaceA componentC = null;
private @Autowire InterfaceA _privateComponentC = null;
public InterfaceA privateComponentC()
{
public InterfaceA privateComponentC() {
return _privateComponentC;
}
}
class DummyAttribute
{
class DummyAttribute {
};
class ComponentE
{
class ComponentE {
@DummyAttribute public ComponentC componentC;
}
class ComponentDeclarationCocktail
{
class ComponentDeclarationCocktail {
alias noomer = int;
@Autowire public ComponentA componentA;
public void doesNothing()
{
public void doesNothing() {
}
~this()
{
~this() {
}
}
class ComponentX : InterfaceA
{
class ComponentX : InterfaceA {
}
class ComponentZ : ComponentB
{
class ComponentZ : ComponentB {
}
class MonkeyShine
{
class MonkeyShine {
@Autowire!ComponentX public InterfaceA component;
}
class BootstrapBootstrap
{
class BootstrapBootstrap {
@Autowire!ComponentX public InterfaceA componentX;
@Autowire!ComponentC public InterfaceA componentC;
}
class LordOfTheComponents
{
class LordOfTheComponents {
@Autowire public InterfaceA[] components;
}
class ComponentCharlie
{
class ComponentCharlie {
@Autowire @AssignNewInstance public ComponentA componentA;
}
class OuttaTime
{
class OuttaTime {
@Autowire @OptionalDependency public InterfaceA interfaceA;
@Autowire @OptionalDependency public ComponentA componentA;
@ -103,537 +84,423 @@ version (unittest)
@Autowire @OptionalDependency public ComponentC[] componentCs;
}
class ValuedClass
{
class ValuedClass {
@Value("values.int")
public int intValue;
@Autowire public ComponentA unrelated;
}
class TestInjector : ValueInjector!int
{
public override int get(string key)
{
class TestInjector : ValueInjector!int {
public override int get(string key) {
assert(key == "values.int");
return 8;
}
}
interface TestInterface
{
interface TestInterface {
}
class TestClass : TestInterface
{
class TestClass : TestInterface {
}
class TestClassDeux : TestInterface
{
class TestClassDeux : TestInterface {
@Autowire public UnrelatedClass unrelated;
}
class UnrelatedClass
{
class UnrelatedClass {
}
class FailOnCreationClass
{
this()
{
class FailOnCreationClass {
this() {
throw new Exception("This class should not be instantiated");
}
}
class AutowiredClass
{
class AutowiredClass {
}
class ComponentClass
{
class ComponentClass {
@Autowire public AutowiredClass autowiredClass;
}
class ComponentCat
{
class ComponentCat {
@Autowire public ComponentMouse mouse;
}
class ComponentMouse
{
class ComponentMouse {
@Autowire public ComponentCat cat;
}
class Eenie
{
class Eenie {
@Autowire public Meenie meenie;
}
class Meenie
{
class Meenie {
@Autowire public Moe moe;
}
class Moe
{
class Moe {
@Autowire public Eenie eenie;
}
class Ittie
{
class Ittie {
@Autowire public Bittie bittie;
}
class Bittie
{
class Bittie {
@Autowire public Bunena banana;
}
class Bunena
{
class Bunena {
@Autowire public Bittie bittie;
}
interface SuperInterface
{
interface SuperInterface {
}
class SuperImplementation : SuperInterface
{
class SuperImplementation : SuperInterface {
@Autowire public Bunena banana;
}
interface Color
{
interface Color {
}
class Blue : Color
{
class Blue : Color {
}
class Red : Color
{
class Red : Color {
}
class Spiders
{
class Spiders {
@Autowire public TestInterface testMember;
}
class Recursive
{
class Recursive {
@Autowire public Recursive recursive;
}
class Moolah
{
class Moolah {
}
class Wants
{
class Wants {
@Autowire public Moolah moolah;
}
class John
{
class John {
@Autowire public Wants wants;
}
class Cocktail
{
class Cocktail {
@Autowire public Moolah moolah;
public Red red;
this(Red red)
{
this(Red red) {
this.red = red;
}
}
class Wallpaper
{
class Wallpaper {
public Color color;
this(Color color)
{
this(Color color) {
this.color = color;
}
}
class Pot
{
this(Kettle kettle)
{
class Pot {
this(Kettle kettle) {
}
}
class Kettle
{
this(Pot pot)
{
class Kettle {
this(Pot pot) {
}
}
class Rock
{
this(Scissors scissors)
{
class Rock {
this(Scissors scissors) {
}
}
class Paper
{
this(Rock rock)
{
class Paper {
this(Rock rock) {
}
}
class Scissors
{
this(Paper paper)
{
class Scissors {
this(Paper paper) {
}
}
class Hello
{
this(Ola ola)
{
class Hello {
this(Ola ola) {
}
}
class PostConstructionDependency
{
class PostConstructionDependency {
public bool postConstructWasCalled = false;
@PostConstruct public void callMeMaybe()
{
@PostConstruct public void callMeMaybe() {
postConstructWasCalled = true;
}
}
class ChildOfPostConstruction : PostConstructionDependency
{
class ChildOfPostConstruction : PostConstructionDependency {
}
interface ThereWillBePostConstruction
{
interface ThereWillBePostConstruction {
@PostConstruct void constructIt();
}
class ButThereWontBe : ThereWillBePostConstruction
{
class ButThereWontBe : ThereWillBePostConstruction {
public bool postConstructWasCalled = false;
public override void constructIt()
{
public override void constructIt() {
postConstructWasCalled = true;
}
}
class PostConstructWithAutowiring
{
class PostConstructWithAutowiring {
@Autowire private PostConstructionDependency dependency;
@Value("")
private int theNumber = 1;
@PostConstruct public void doIt()
{
@PostConstruct public void doIt() {
assert(theNumber == 8783);
assert(dependency !is null);
}
}
class PreDestroyerOfFates
{
class PreDestroyerOfFates {
public bool preDestroyWasCalled = false;
@PreDestroy public void callMeMaybe()
{
@PreDestroy public void callMeMaybe() {
preDestroyWasCalled = true;
}
}
class PostConstructingIntInjector : ValueInjector!int
{
int get(string key)
{
class PostConstructingIntInjector : ValueInjector!int {
int get(string key) {
return 8783;
}
}
interface Fruit
{
interface Fruit {
string getShape();
}
interface Animal
{
interface Animal {
string getYell();
}
class Banana
{
class Banana {
public string color;
this(string color)
{
this(string color) {
this.color = color;
}
}
class Apple
{
class Apple {
}
class Pear : Fruit
{
public override string getShape()
{
class Pear : Fruit {
public override string getShape() {
return "Pear shaped";
}
}
class Rabbit : Animal
{
public override string getYell()
{
class Rabbit : Animal {
public override string getYell() {
return "Squeeeeeel";
}
}
class Wolf : Animal
{
public override string getYell()
{
class Wolf : Animal {
public override string getYell() {
return "Wooooooooooo";
}
}
class PieChart
{
class PieChart {
}
class CakeChart : PieChart
{
class CakeChart : PieChart {
}
class ClassWrapper
{
class ClassWrapper {
public Object someClass;
this(Object someClass)
{
this(Object someClass) {
this.someClass = someClass;
}
}
class ClassWrapperWrapper
{
class ClassWrapperWrapper {
public ClassWrapper wrapper;
this(ClassWrapper wrapper)
{
this(ClassWrapper wrapper) {
this.wrapper = wrapper;
}
}
class SimpleContext : ApplicationContext
{
public override void registerDependencies(shared(DependencyContainer) container)
{
class SimpleContext : ApplicationContext {
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!CakeChart;
}
@Component public Apple apple()
{
@Component public Apple apple() {
return new Apple();
}
}
class ComplexAutowiredTestContext : ApplicationContext
{
class ComplexAutowiredTestContext : ApplicationContext {
@Autowire private Apple apple;
@Autowire protected ClassWrapper classWrapper;
public override void registerDependencies(shared(DependencyContainer) container)
{
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!Apple;
}
@Component public ClassWrapper wrapper()
{
@Component public ClassWrapper wrapper() {
return new ClassWrapper(apple);
}
@Component public ClassWrapperWrapper wrapperWrapper()
{
@Component public ClassWrapperWrapper wrapperWrapper() {
return new ClassWrapperWrapper(classWrapper);
}
}
class AutowiredTestContext : ApplicationContext
{
class AutowiredTestContext : ApplicationContext {
@Autowire private Apple apple;
@Component public ClassWrapper wrapper()
{
@Component public ClassWrapper wrapper() {
return new ClassWrapper(apple);
}
}
class TestContext : ApplicationContext
{
class TestContext : ApplicationContext {
@Component public Banana banana()
{
@Component public Banana banana() {
return new Banana("Yellow");
}
public Apple apple()
{
public Apple apple() {
return new Apple();
}
@Component @RegisterByType!Fruit public Pear pear()
{
@Component @RegisterByType!Fruit public Pear pear() {
return new Pear();
}
@Component @RegisterByType!Animal public Rabbit rabbit()
{
@Component @RegisterByType!Animal public Rabbit rabbit() {
return new Rabbit();
}
@Component @RegisterByType!Animal public Wolf wolf()
{
@Component @RegisterByType!Animal public Wolf wolf() {
return new Wolf();
}
@Component @Prototype public PieChart pieChart()
{
@Component @Prototype public PieChart pieChart() {
return new PieChart();
}
}
class TestImplementation : TestInterface
{
class TestImplementation : TestInterface {
public string someContent = "";
}
class SomeOtherClassThen
{
class SomeOtherClassThen {
}
class ClassWithConstructor
{
class ClassWithConstructor {
public TestImplementation testImplementation;
this(TestImplementation testImplementation)
{
this(TestImplementation testImplementation) {
this.testImplementation = testImplementation;
}
}
class ClassWithMultipleConstructors
{
class ClassWithMultipleConstructors {
public SomeOtherClassThen someOtherClassThen;
public TestImplementation testImplementation;
this(SomeOtherClassThen someOtherClassThen)
{
this(SomeOtherClassThen someOtherClassThen) {
this.someOtherClassThen = someOtherClassThen;
}
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation)
{
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) {
this.someOtherClassThen = someOtherClassThen;
this.testImplementation = testImplementation;
}
}
class ClassWithConstructorWithMultipleParameters
{
class ClassWithConstructorWithMultipleParameters {
public SomeOtherClassThen someOtherClassThen;
public TestImplementation testImplementation;
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation)
{
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) {
this.someOtherClassThen = someOtherClassThen;
this.testImplementation = testImplementation;
}
}
class ClassWithPrimitiveConstructor
{
class ClassWithPrimitiveConstructor {
public SomeOtherClassThen someOtherClassThen;
this(string willNotBePicked)
{
this(string willNotBePicked) {
}
this(SomeOtherClassThen someOtherClassThen)
{
this(SomeOtherClassThen someOtherClassThen) {
this.someOtherClassThen = someOtherClassThen;
}
}
class ClassWithEmptyConstructor
{
class ClassWithEmptyConstructor {
public SomeOtherClassThen someOtherClassThen;
this()
{
this() {
}
this(SomeOtherClassThen someOtherClassThen)
{
this(SomeOtherClassThen someOtherClassThen) {
this.someOtherClassThen = someOtherClassThen;
}
}
class ClassWithNonInjectableConstructor
{
this(string myName)
{
class ClassWithNonInjectableConstructor {
this(string myName) {
}
}
class ClassWithStructConstructor
{
class ClassWithStructConstructor {
public SomeOtherClassThen someOtherClassThen;
this(Thing willNotBePicked)
{
this(Thing willNotBePicked) {
}
this(SomeOtherClassThen someOtherClassThen)
{
this(SomeOtherClassThen someOtherClassThen) {
this.someOtherClassThen = someOtherClassThen;
}
}
class TestType
{
class TestType {
}
class Dependency
{
class Dependency {
}
struct Thing
{
struct Thing {
int x;
}
class MyConfig
{
class MyConfig {
@Value("conf.stuffs")
int stuffs;
@ -644,105 +511,83 @@ version (unittest)
Thing thing;
}
class ConfigWithDefaults
{
class ConfigWithDefaults {
@Value("conf.missing")
int noms = 9;
}
class ConfigWithMandatory
{
class ConfigWithMandatory {
@MandatoryValue("conf.mustbethere")
int nums;
}
class IntInjector : ValueInjector!int
{
public override int get(string key)
{
class IntInjector : ValueInjector!int {
public override int get(string key) {
assert(key == "conf.stuffs");
return 364;
}
}
class StringInjector : ValueInjector!string
{
public override string get(string key)
{
class StringInjector : ValueInjector!string {
public override string get(string key) {
assert(key == "conf.name");
return "Le Chef";
}
}
class ThingInjector : ValueInjector!Thing
{
public override Thing get(string key)
{
class ThingInjector : ValueInjector!Thing {
public override Thing get(string key) {
assert(key == "conf.thing");
return Thing(8899);
}
}
class DefaultIntInjector : ValueInjector!int
{
public override int get(string key)
{
class DefaultIntInjector : ValueInjector!int {
public override int get(string key) {
throw new ValueNotAvailableException(key);
}
}
class MandatoryAvailableIntInjector : ValueInjector!int
{
public override int get(string key)
{
class MandatoryAvailableIntInjector : ValueInjector!int {
public override int get(string key) {
return 7466;
}
}
class MandatoryUnavailableIntInjector : ValueInjector!int
{
public override int get(string key)
{
class MandatoryUnavailableIntInjector : ValueInjector!int {
public override int get(string key) {
throw new ValueNotAvailableException(key);
}
}
class DependencyInjectedIntInjector : ValueInjector!int
{
class DependencyInjectedIntInjector : ValueInjector!int {
@Autowire public Dependency dependency;
public override int get(string key)
{
public override int get(string key) {
return 2345;
}
}
class CircularIntInjector : ValueInjector!int
{
class CircularIntInjector : ValueInjector!int {
@Autowire public ValueInjector!int dependency;
private int count = 0;
public override int get(string key)
{
public override int get(string key) {
count += 1;
if (count >= 3)
{
if (count >= 3) {
return count;
}
return dependency.get(key);
}
}
class ValueInjectedIntInjector : ValueInjector!int
{
class ValueInjectedIntInjector : ValueInjector!int {
@Value("five")
public int count = 0;
public override int get(string key)
{
if (key == "five")
{
public override int get(string key) {
if (key == "five") {
return 5;
}
@ -750,14 +595,11 @@ version (unittest)
}
}
class DependencyValueInjectedIntInjector : ValueInjector!int
{
class DependencyValueInjectedIntInjector : ValueInjector!int {
@Autowire public ConfigWithDefaults config;
public override int get(string key)
{
if (key == "conf.missing")
{
public override int get(string key) {
if (key == "conf.missing") {
return 8899;
}
@ -765,57 +607,46 @@ version (unittest)
}
}
class TemplatedComponent(T)
{
class TemplatedComponent(T) {
@Autowire T instance;
}
class CircularTemplateComponentA : TemplatedComponent!CircularTemplateComponentB
{
class CircularTemplateComponentA : TemplatedComponent!CircularTemplateComponentB {
}
class CircularTemplateComponentB : TemplatedComponent!CircularTemplateComponentA
{
class CircularTemplateComponentB : TemplatedComponent!CircularTemplateComponentA {
}
class ClassWithTemplatedConstructorArg(T)
{
class ClassWithTemplatedConstructorArg(T) {
public TemplatedComponent!T dependency;
this(TemplatedComponent!T assignedDependency)
{
this(TemplatedComponent!T assignedDependency) {
this.dependency = assignedDependency;
}
}
class Grandma
{
class Grandma {
}
class Mommy : Grandma
{
class Mommy : Grandma {
}
class Kid : Mommy
{
class Kid : Mommy {
}
class AutowiredMethod
{
class AutowiredMethod {
@Autowire
public int lala()
{
public int lala() {
return 42;
}
@Autowire
public int lala(int valla)
{
public int lala(int valla) {
return valla;
}
}

View file

@ -5,6 +5,5 @@
* The full terms of the license can be found in the LICENSE file.
*/
void main()
{
void main() {
}

View file

@ -10,32 +10,26 @@ import poodinis.test.testclasses;
import std.exception;
version (unittest)
{
version (unittest) {
struct LocalStruct
{
struct LocalStruct {
bool wasInjected = false;
}
class LocalStructInjector : ValueInjector!LocalStruct
{
public override LocalStruct get(string key)
{
class LocalStructInjector : ValueInjector!LocalStruct {
public override LocalStruct get(string key) {
auto data = LocalStruct(true);
return data;
}
}
class LocalClassWithStruct
{
class LocalClassWithStruct {
@Value("")
public LocalStruct localStruct;
}
// Test injection of values
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!MyConfig;
container.register!(ValueInjector!int, IntInjector);
@ -49,8 +43,7 @@ version (unittest)
}
// Test injection of values throws exception when injector is not there
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!MyConfig;
assertThrown!ResolveException(container.resolve!MyConfig);
@ -59,8 +52,7 @@ version (unittest)
}
// Test injection of values with defaults
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ConfigWithDefaults;
container.register!(ValueInjector!int, DefaultIntInjector);
@ -70,8 +62,7 @@ version (unittest)
}
// Test mandatory injection of values which are available
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ConfigWithMandatory;
container.register!(ValueInjector!int, MandatoryAvailableIntInjector);
@ -81,8 +72,7 @@ version (unittest)
}
// Test mandatory injection of values which are not available
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ConfigWithMandatory;
container.register!(ValueInjector!int, MandatoryUnavailableIntInjector);
@ -92,8 +82,7 @@ version (unittest)
}
// Test injecting dependencies within value injectors
unittest
{
unittest {
auto container = new shared DependencyContainer();
auto dependency = new Dependency();
container.register!Dependency.existingInstance(dependency);
@ -104,8 +93,7 @@ version (unittest)
}
// Test injecting circular dependencies within value injectors
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(ValueInjector!int, CircularIntInjector);
auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int);
@ -115,8 +103,7 @@ version (unittest)
}
// Test value injection within value injectors
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(ValueInjector!int, ValueInjectedIntInjector);
auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int);
@ -125,8 +112,7 @@ version (unittest)
}
// Test value injection within dependencies of value injectors
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!ConfigWithDefaults;
@ -138,8 +124,7 @@ version (unittest)
}
// Test resolving locally defined struct injector (github issue #20)
unittest
{
unittest {
auto container = new shared DependencyContainer();
container.register!(ValueInjector!LocalStruct, LocalStructInjector);
container.register!LocalClassWithStruct;