mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
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:
parent
6d1bf44d28
commit
9b05aa3af9
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"dfmt.braceStyle": "allman"
|
"dfmt.braceStyle": "otbs"
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import poodinis;
|
||||||
|
|
||||||
class Driver {}
|
class Driver {}
|
||||||
|
|
||||||
interface Database {};
|
interface Database {}
|
||||||
|
|
||||||
class RelationalDatabase : Database {
|
class RelationalDatabase : Database {
|
||||||
private Driver driver;
|
private Driver driver;
|
||||||
|
|
|
@ -12,53 +12,42 @@ import std.digest.md;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
|
|
||||||
class SecurityAuditor
|
class SecurityAuditor {
|
||||||
{
|
public void submitAudit() {
|
||||||
public void submitAudit()
|
|
||||||
{
|
|
||||||
writeln("Hmmmyes I have received your audit. It is.... adequate.");
|
writeln("Hmmmyes I have received your audit. It is.... adequate.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SuperSecurityDevice
|
class SuperSecurityDevice {
|
||||||
{
|
|
||||||
private int seed;
|
private int seed;
|
||||||
|
|
||||||
public this()
|
public this() {
|
||||||
{
|
|
||||||
auto randomGenerator = Random(unpredictableSeed);
|
auto randomGenerator = Random(unpredictableSeed);
|
||||||
seed = uniform(0, 999, randomGenerator);
|
seed = uniform(0, 999, randomGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getPassword()
|
public string getPassword() {
|
||||||
{
|
|
||||||
return to!string(seed) ~ "t1m3sp13!!:";
|
return to!string(seed) ~ "t1m3sp13!!:";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SecurityManager
|
class SecurityManager {
|
||||||
{
|
|
||||||
@Autowire private SuperSecurityDevice levelOneSecurity;
|
@Autowire private SuperSecurityDevice levelOneSecurity;
|
||||||
|
|
||||||
@Autowire @AssignNewInstance private SuperSecurityDevice levelTwoSecurity;
|
@Autowire @AssignNewInstance private SuperSecurityDevice levelTwoSecurity;
|
||||||
|
|
||||||
@Autowire @OptionalDependency private SecurityAuditor auditor;
|
@Autowire @OptionalDependency private SecurityAuditor auditor;
|
||||||
|
|
||||||
public void doAudit()
|
public void doAudit() {
|
||||||
{
|
if (auditor !is null) {
|
||||||
if (auditor !is null)
|
|
||||||
{
|
|
||||||
auditor.submitAudit();
|
auditor.submitAudit();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeln("I uh, will skip the audit for now...");
|
writeln("I uh, will skip the audit for now...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope
|
dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope
|
||||||
dependencies.register!SecurityManager;
|
dependencies.register!SecurityManager;
|
||||||
|
@ -68,12 +57,9 @@ void main()
|
||||||
writeln("Password for user one: " ~ manager.levelOneSecurity.getPassword());
|
writeln("Password for user one: " ~ manager.levelOneSecurity.getPassword());
|
||||||
writeln("Password for user two: " ~ manager.levelTwoSecurity.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.
|
writeln("SECURITY BREACH!!!!!"); // Should not be printed since levelTwoSecurity is a new instance.
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeln("Security okay!");
|
writeln("Security okay!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,64 +9,50 @@ import poodinis;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
class TownSquare
|
class TownSquare {
|
||||||
{
|
|
||||||
|
|
||||||
@Autowire private MarketStall marketStall;
|
@Autowire private MarketStall marketStall;
|
||||||
|
|
||||||
public void makeSound()
|
public void makeSound() {
|
||||||
{
|
|
||||||
marketStall.announceGoodsForSale();
|
marketStall.announceGoodsForSale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Goods
|
interface Goods {
|
||||||
{
|
|
||||||
public string getGoodsName();
|
public string getGoodsName();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Fish : Goods
|
class Fish : Goods {
|
||||||
{
|
public override string getGoodsName() {
|
||||||
public override string getGoodsName()
|
|
||||||
{
|
|
||||||
return "Fish";
|
return "Fish";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MarketStall
|
class MarketStall {
|
||||||
{
|
|
||||||
private Goods goods;
|
private Goods goods;
|
||||||
|
|
||||||
this(Goods goods)
|
this(Goods goods) {
|
||||||
{
|
|
||||||
this.goods = goods;
|
this.goods = goods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void announceGoodsForSale()
|
public void announceGoodsForSale() {
|
||||||
{
|
|
||||||
writeln(goods.getGoodsName() ~ " for sale!");
|
writeln(goods.getGoodsName() ~ " for sale!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExampleApplicationContext : ApplicationContext
|
class ExampleApplicationContext : ApplicationContext {
|
||||||
{
|
|
||||||
|
|
||||||
@Autowire private Goods goods;
|
@Autowire private Goods goods;
|
||||||
|
|
||||||
public override void registerDependencies(shared(DependencyContainer) container)
|
public override void registerDependencies(shared(DependencyContainer) container) {
|
||||||
{
|
|
||||||
container.register!(Goods, Fish);
|
container.register!(Goods, Fish);
|
||||||
container.register!TownSquare;
|
container.register!TownSquare;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component public MarketStall marketStall()
|
@Component public MarketStall marketStall() {
|
||||||
{
|
|
||||||
return new MarketStall(goods);
|
return new MarketStall(goods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!ExampleApplicationContext;
|
container.registerContext!ExampleApplicationContext;
|
||||||
|
|
||||||
|
|
|
@ -9,50 +9,39 @@ import poodinis;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
interface Pie
|
interface Pie {
|
||||||
{
|
|
||||||
public void eat();
|
public void eat();
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlueBerryPie : Pie
|
class BlueBerryPie : Pie {
|
||||||
{
|
public override void eat() {
|
||||||
public override void eat()
|
|
||||||
{
|
|
||||||
writeln("Nom nom nom. I like this one!");
|
writeln("Nom nom nom. I like this one!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApplePie : Pie
|
class ApplePie : Pie {
|
||||||
{
|
public override void eat() {
|
||||||
public override void eat()
|
|
||||||
{
|
|
||||||
writeln("Nom nom nom. These aren't real apples...");
|
writeln("Nom nom nom. These aren't real apples...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CardboardBoxPie : Pie
|
class CardboardBoxPie : Pie {
|
||||||
{
|
public override void eat() {
|
||||||
public override void eat()
|
|
||||||
{
|
|
||||||
writeln("Nom nom nom. This... is not a pie.");
|
writeln("Nom nom nom. This... is not a pie.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PieEater
|
class PieEater {
|
||||||
{
|
|
||||||
@Autowire private Pie[] pies;
|
@Autowire private Pie[] pies;
|
||||||
|
|
||||||
public void eatThemAll()
|
public void eatThemAll() {
|
||||||
{
|
foreach (pie; pies) {
|
||||||
foreach (pie; pies)
|
|
||||||
{
|
|
||||||
pie.eat();
|
pie.eat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!(Pie, BlueBerryPie);
|
dependencies.register!(Pie, BlueBerryPie);
|
||||||
dependencies.register!(Pie, ApplePie);
|
dependencies.register!(Pie, ApplePie);
|
||||||
|
|
|
@ -7,64 +7,52 @@
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
class Scheduler
|
class Scheduler {
|
||||||
{
|
|
||||||
private Calendar calendar;
|
private Calendar calendar;
|
||||||
|
|
||||||
// All parameters will autmatically be assigned when Scheduler is created.
|
// All parameters will autmatically be assigned when Scheduler is created.
|
||||||
this(Calendar calendar)
|
this(Calendar calendar) {
|
||||||
{
|
|
||||||
this.calendar = calendar;
|
this.calendar = calendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scheduleJob()
|
public void scheduleJob() {
|
||||||
{
|
|
||||||
calendar.findOpenDate();
|
calendar.findOpenDate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Calendar
|
class Calendar {
|
||||||
{
|
|
||||||
private HardwareClock hardwareClock;
|
private HardwareClock hardwareClock;
|
||||||
|
|
||||||
// This constructor contains built-in type "int" and thus will not be used.
|
// 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 constructor is chosen instead as candidate for injection when Calendar is created.
|
||||||
this(HardwareClock hardwareClock)
|
this(HardwareClock hardwareClock) {
|
||||||
{
|
|
||||||
this.hardwareClock = hardwareClock;
|
this.hardwareClock = hardwareClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void findOpenDate()
|
public void findOpenDate() {
|
||||||
{
|
|
||||||
hardwareClock.doThings();
|
hardwareClock.doThings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HardwareClock
|
class HardwareClock {
|
||||||
{
|
|
||||||
// Parameterless constructors will halt any further selection of constructors.
|
// Parameterless constructors will halt any further selection of constructors.
|
||||||
this()
|
this() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// As a result, this constructor will not be used when HardwareClock is created.
|
// 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");
|
throw new Exception("This constructor should not be used by Poodinis");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doThings()
|
public void doThings() {
|
||||||
{
|
|
||||||
writeln("Things are being done!");
|
writeln("Things are being done!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
import poodinis; // Locally imported to emphasize that classes do not depend on Poodinis.
|
import poodinis; // Locally imported to emphasize that classes do not depend on Poodinis.
|
||||||
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
|
|
|
@ -8,12 +8,10 @@
|
||||||
import poodinis;
|
import poodinis;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
class Doohickey
|
class Doohickey {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!Doohickey.initializedBy({
|
dependencies.register!Doohickey.initializedBy({
|
||||||
writeln("Creating Doohickey via initializer delegate.");
|
writeln("Creating Doohickey via initializer delegate.");
|
||||||
|
|
|
@ -9,44 +9,34 @@ import poodinis;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
class ADependency
|
class ADependency {
|
||||||
{
|
@PostConstruct public void postConstructor() {
|
||||||
@PostConstruct public void postConstructor()
|
|
||||||
{
|
|
||||||
writeln("The dependency is created.");
|
writeln("The dependency is created.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callMe()
|
public void callMe() {
|
||||||
{
|
|
||||||
writeln("The dependency was called.");
|
writeln("The dependency was called.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AClass
|
class AClass {
|
||||||
{
|
|
||||||
@Autowire public ADependency dependency; // Dependencies are autowired before the post-constructor is called.
|
@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.");
|
writeln("The class is created.");
|
||||||
if (dependency !is null)
|
if (dependency !is null) {
|
||||||
{
|
|
||||||
writeln("The dependency is autowired.");
|
writeln("The dependency is autowired.");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeln("The dependency was NOT autowired.");
|
writeln("The dependency was NOT autowired.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreDestroy public void preDestructor()
|
@PreDestroy public void preDestructor() {
|
||||||
{
|
|
||||||
writeln("The class is no longer registered with the container.");
|
writeln("The class is no longer registered with the container.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void main()
|
public void main() {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ADependency).onConstructed((Object obj) {
|
container.register!(ADependency).onConstructed((Object obj) {
|
||||||
writeln("ADependency constructed");
|
writeln("ADependency constructed");
|
||||||
|
|
|
@ -9,50 +9,39 @@ import poodinis;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
interface Engine
|
interface Engine {
|
||||||
{
|
|
||||||
public void engage();
|
public void engage();
|
||||||
}
|
}
|
||||||
|
|
||||||
class FuelEngine : Engine
|
class FuelEngine : Engine {
|
||||||
{
|
public void engage() {
|
||||||
public void engage()
|
|
||||||
{
|
|
||||||
writeln("VROOOOOOM!");
|
writeln("VROOOOOOM!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ElectricEngine : Engine
|
class ElectricEngine : Engine {
|
||||||
{
|
public void engage() {
|
||||||
public void engage()
|
|
||||||
{
|
|
||||||
writeln("hummmmmmmm....");
|
writeln("hummmmmmmm....");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HybridCar
|
class HybridCar {
|
||||||
{
|
|
||||||
alias KilometersPerHour = int;
|
alias KilometersPerHour = int;
|
||||||
|
|
||||||
@Autowire!FuelEngine private Engine fuelEngine;
|
@Autowire!FuelEngine private Engine fuelEngine;
|
||||||
|
|
||||||
@Autowire!ElectricEngine private Engine electricEngine;
|
@Autowire!ElectricEngine private Engine electricEngine;
|
||||||
|
|
||||||
public void moveAtSpeed(KilometersPerHour speed)
|
public void moveAtSpeed(KilometersPerHour speed) {
|
||||||
{
|
if (speed <= 45) {
|
||||||
if (speed <= 45)
|
|
||||||
{
|
|
||||||
electricEngine.engage();
|
electricEngine.engage();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fuelEngine.engage();
|
fuelEngine.engage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
|
|
||||||
dependencies.register!HybridCar;
|
dependencies.register!HybridCar;
|
||||||
|
|
|
@ -7,31 +7,25 @@
|
||||||
|
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
class Driver
|
class Driver {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Database
|
interface Database {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RelationalDatabase : Database
|
class RelationalDatabase : Database {
|
||||||
{
|
|
||||||
private Driver driver;
|
private Driver driver;
|
||||||
|
|
||||||
this(Driver driver)
|
this(Driver driver) { // Automatically injected on creation by container
|
||||||
{ // Automatically injected on creation by container
|
|
||||||
this.driver = driver;
|
this.driver = driver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataWriter
|
class DataWriter {
|
||||||
{
|
|
||||||
@Autowire private Database database; // Automatically injected when class is resolved
|
@Autowire private Database database; // Automatically injected when class is resolved
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!Driver;
|
dependencies.register!Driver;
|
||||||
dependencies.register!DataWriter;
|
dependencies.register!DataWriter;
|
||||||
|
|
|
@ -7,28 +7,23 @@
|
||||||
|
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
class Violin
|
class Violin {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InstrumentPlayer
|
interface InstrumentPlayer {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViolinPlayer : InstrumentPlayer
|
class ViolinPlayer : InstrumentPlayer {
|
||||||
{
|
|
||||||
// Autowired concrete types can be registered on resolve
|
// Autowired concrete types can be registered on resolve
|
||||||
@Autowire private Violin violin;
|
@Autowire private Violin violin;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Orchestra
|
class Orchestra {
|
||||||
{
|
|
||||||
// Autowired non-concrete types can be registered on resolved, given they have a qualifier.
|
// Autowired non-concrete types can be registered on resolved, given they have a qualifier.
|
||||||
@Autowire!ViolinPlayer private InstrumentPlayer violinPlayer;
|
@Autowire!ViolinPlayer private InstrumentPlayer violinPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,12 +10,9 @@ import poodinis;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.string;
|
import std.string;
|
||||||
|
|
||||||
class IntValueInjector : ValueInjector!int
|
class IntValueInjector : ValueInjector!int {
|
||||||
{
|
int get(string key) {
|
||||||
int get(string key)
|
switch (key) {
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case "http.port":
|
case "http.port":
|
||||||
return 8080;
|
return 8080;
|
||||||
case "http.keep_alive":
|
case "http.keep_alive":
|
||||||
|
@ -26,12 +23,9 @@ class IntValueInjector : ValueInjector!int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringValueInjector : ValueInjector!string
|
class StringValueInjector : ValueInjector!string {
|
||||||
{
|
string get(string key) {
|
||||||
string get(string key)
|
switch (key) {
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case "http.hostname":
|
case "http.hostname":
|
||||||
return "acme.org";
|
return "acme.org";
|
||||||
default:
|
default:
|
||||||
|
@ -40,8 +34,7 @@ class StringValueInjector : ValueInjector!string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HttpServer
|
class HttpServer {
|
||||||
{
|
|
||||||
|
|
||||||
@Value("http.port")
|
@Value("http.port")
|
||||||
private int port = 80;
|
private int port = 80;
|
||||||
|
@ -55,15 +48,13 @@ class HttpServer
|
||||||
@MandatoryValue("http.keep_alive")
|
@MandatoryValue("http.keep_alive")
|
||||||
private int keepAliveTime; // A ResolveException is thrown when the value is not available, default assignments are not used.
|
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",
|
writeln(format("Serving pages for %s:%s with max connection count of %s",
|
||||||
hostName, port, maxConnections));
|
hostName, port, maxConnections));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!(ValueInjector!int, IntValueInjector);
|
dependencies.register!(ValueInjector!int, IntValueInjector);
|
||||||
dependencies.register!(ValueInjector!string, StringValueInjector);
|
dependencies.register!(ValueInjector!string, StringValueInjector);
|
||||||
|
|
|
@ -20,25 +20,17 @@
|
||||||
|
|
||||||
module poodinis.altphobos;
|
module poodinis.altphobos;
|
||||||
|
|
||||||
template isFunction(X...)
|
template isFunction(X...) {
|
||||||
{
|
static if (X.length == 1) {
|
||||||
static if (X.length == 1)
|
static if (is(typeof(&X[0]) U : U*) && is(U == function) || is(typeof(&X[0]) U == delegate)) {
|
||||||
{
|
|
||||||
static if (is(typeof(&X[0]) U : U*) && is(U == function) || is(typeof(&X[0]) U == delegate))
|
|
||||||
{
|
|
||||||
// x is a (nested) function symbol.
|
// x is a (nested) function symbol.
|
||||||
enum isFunction = true;
|
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.
|
// x is a type. Take the type of it and examine.
|
||||||
enum isFunction = is(T == function);
|
enum isFunction = is(T == function);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
enum isFunction = false;
|
enum isFunction = false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
enum isFunction = false;
|
enum isFunction = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,11 @@ import std.string : format;
|
||||||
import std.traits : BaseClassesTuple, FieldNameTuple, fullyQualifiedName, hasUDA, isDynamicArray;
|
import std.traits : BaseClassesTuple, FieldNameTuple, fullyQualifiedName, hasUDA, isDynamicArray;
|
||||||
import std.range : ElementType;
|
import std.range : ElementType;
|
||||||
|
|
||||||
debug
|
debug {
|
||||||
{
|
|
||||||
import std.stdio : writeln;
|
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"
|
* 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"
|
* 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;
|
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.
|
* Optional dependencies will not lead to a resolveException when there is no type registered for them.
|
||||||
* The member will remain null.
|
* 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.
|
* antenna will always be assigned a new instance of class Antenna.
|
||||||
*/
|
*/
|
||||||
struct AssignNewInstance
|
struct AssignNewInstance {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress)
|
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) {
|
||||||
{
|
debug {
|
||||||
debug
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress));
|
writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,65 +113,48 @@ private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAd
|
||||||
*
|
*
|
||||||
* See_Also: Autowire
|
* See_Also: Autowire
|
||||||
*/
|
*/
|
||||||
public void autowire(Type)(shared(DependencyContainer) container, Type instance)
|
public void autowire(Type)(shared(DependencyContainer) container, Type instance) {
|
||||||
{
|
debug (poodinisVerbose) {
|
||||||
debug (poodinisVerbose)
|
|
||||||
{
|
|
||||||
printDebugAutowiredInstance(typeid(Type), &instance);
|
printDebugAutowiredInstance(typeid(Type), &instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recurse into base class if there are more between Type and Object in the hierarchy
|
// 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);
|
autowire!(BaseClassesTuple!Type[0])(container, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (index, name; FieldNameTuple!Type)
|
foreach (index, name; FieldNameTuple!Type) {
|
||||||
{
|
|
||||||
autowireMember!(name, index, Type)(container, instance);
|
autowireMember!(name, index, Type)(container, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType,
|
private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType,
|
||||||
void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member)
|
void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) {
|
||||||
{
|
debug {
|
||||||
debug
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType,
|
writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType,
|
||||||
candidateInstanceAddress, instanceType, instanceAddress, member));
|
candidateInstanceAddress, instanceType, instanceAddress, member));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugAutowiringArray(TypeInfo superTypeInfo,
|
private void printDebugAutowiringArray(TypeInfo superTypeInfo,
|
||||||
TypeInfo instanceType, void* instanceAddress, string member)
|
TypeInfo instanceType, void* instanceAddress, string member) {
|
||||||
{
|
debug {
|
||||||
debug
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s",
|
writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s",
|
||||||
superTypeInfo, instanceType, instanceAddress, member));
|
superTypeInfo, instanceType, instanceAddress, member));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void autowireMember(string member, size_t memberIndex, Type)(
|
private void autowireMember(string member, size_t memberIndex, Type)(
|
||||||
shared(DependencyContainer) container, Type instance)
|
shared(DependencyContainer) container, Type instance) {
|
||||||
{
|
foreach (attribute; __traits(getAttributes, Type.tupleof[memberIndex])) {
|
||||||
foreach (attribute; __traits(getAttributes, Type.tupleof[memberIndex]))
|
static if (is(attribute == Autowire!T, T)) {
|
||||||
{
|
|
||||||
static if (is(attribute == Autowire!T, T))
|
|
||||||
{
|
|
||||||
injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance);
|
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);
|
injectInstance!(member, memberIndex, UseMemberType)(container, instance);
|
||||||
}
|
} else static if (is(typeof(attribute) == Value)) {
|
||||||
else static if (is(typeof(attribute) == Value))
|
|
||||||
{
|
|
||||||
enum key = attribute.key;
|
enum key = attribute.key;
|
||||||
injectValue!(member, memberIndex, key, false)(container, instance);
|
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;
|
enum key = attribute.key;
|
||||||
injectValue!(member, memberIndex, key, true)(container, instance);
|
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)(
|
private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(
|
||||||
shared(DependencyContainer) container, Type instance)
|
shared(DependencyContainer) container, Type instance) {
|
||||||
{
|
if (instance.tupleof[memberIndex] is null) {
|
||||||
if (instance.tupleof[memberIndex] is null)
|
|
||||||
{
|
|
||||||
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
||||||
enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency);
|
enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency);
|
||||||
|
|
||||||
static if (isDynamicArray!MemberType)
|
static if (isDynamicArray!MemberType) {
|
||||||
{
|
|
||||||
injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container,
|
injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container,
|
||||||
instance);
|
instance);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container,
|
injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container,
|
||||||
instance);
|
instance);
|
||||||
}
|
}
|
||||||
|
@ -207,107 +178,80 @@ private void injectInstance(string member, size_t memberIndex, QualifierType, Ty
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectMultipleInstances(string member, size_t memberIndex,
|
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;
|
alias MemberElementType = ElementType!MemberType;
|
||||||
static if (isOptional)
|
static if (isOptional) {
|
||||||
{
|
|
||||||
auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
|
auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
auto instances = container.resolveAll!MemberElementType;
|
auto instances = container.resolveAll!MemberElementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.tupleof[memberIndex] = instances;
|
instance.tupleof[memberIndex] = instances;
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectSingleInstance(string member, size_t memberIndex,
|
private void injectSingleInstance(string member, size_t memberIndex,
|
||||||
bool isOptional, MemberType, QualifierType, Type)(
|
bool isOptional, MemberType, QualifierType, Type)(
|
||||||
shared(DependencyContainer) container, Type instance)
|
shared(DependencyContainer) container, Type instance) {
|
||||||
{
|
debug (poodinisVerbose) {
|
||||||
debug (poodinisVerbose)
|
|
||||||
{
|
|
||||||
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance);
|
enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance);
|
||||||
|
|
||||||
MemberType qualifiedInstance;
|
MemberType qualifiedInstance;
|
||||||
static if (!is(QualifierType == UseMemberType))
|
static if (!is(QualifierType == UseMemberType)) {
|
||||||
{
|
|
||||||
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType,
|
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType,
|
||||||
assignNewInstance, isOptional)(container);
|
assignNewInstance, isOptional)(container);
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
qualifiedInstanceType = typeid(QualifierType);
|
qualifiedInstanceType = typeid(QualifierType);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType,
|
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType,
|
||||||
assignNewInstance, isOptional)(container);
|
assignNewInstance, isOptional)(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.tupleof[memberIndex] = qualifiedInstance;
|
instance.tupleof[memberIndex] = qualifiedInstance;
|
||||||
|
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
printDebugAutowiringCandidate(qualifiedInstanceType,
|
printDebugAutowiringCandidate(qualifiedInstanceType,
|
||||||
&qualifiedInstance, typeid(Type), &instance, member);
|
&qualifiedInstance, typeid(Type), &instance, member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualifierType createOrResolveInstance(MemberType, QualifierType,
|
private QualifierType createOrResolveInstance(MemberType, QualifierType,
|
||||||
bool createNew, bool isOptional)(shared(DependencyContainer) container)
|
bool createNew, bool isOptional)(shared(DependencyContainer) container) {
|
||||||
{
|
static if (createNew) {
|
||||||
static if (createNew)
|
|
||||||
{
|
|
||||||
auto instanceFactory = new InstanceFactory();
|
auto instanceFactory = new InstanceFactory();
|
||||||
instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType),
|
instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType),
|
||||||
CreatesSingleton.no);
|
CreatesSingleton.no);
|
||||||
return cast(MemberType) instanceFactory.getInstance();
|
return cast(MemberType) instanceFactory.getInstance();
|
||||||
}
|
} else {
|
||||||
else
|
static if (isOptional) {
|
||||||
{
|
|
||||||
static if (isOptional)
|
|
||||||
{
|
|
||||||
return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
|
return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return container.resolve!(MemberType, QualifierType);
|
return container.resolve!(MemberType, QualifierType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(
|
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]);
|
alias MemberType = typeof(Type.tupleof[memberIndex]);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
auto injector = container.resolve!(ValueInjector!MemberType);
|
auto injector = container.resolve!(ValueInjector!MemberType);
|
||||||
instance.tupleof[memberIndex] = injector.get(key);
|
instance.tupleof[memberIndex] = injector.get(key);
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
|
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
|
||||||
}
|
}
|
||||||
}
|
} catch (ResolveException e) {
|
||||||
catch (ResolveException e)
|
|
||||||
{
|
|
||||||
throw new ValueInjectionException(format(
|
throw new ValueInjectionException(format(
|
||||||
"Could not inject value of type %s into %s.%s: value injector is missing for this type.",
|
"Could not inject value of type %s into %s.%s: value injector is missing for this type.",
|
||||||
typeid(MemberType), typeid(Type), member));
|
typeid(MemberType), typeid(Type), member));
|
||||||
}
|
} catch (ValueNotAvailableException e) {
|
||||||
catch (ValueNotAvailableException e)
|
static if (mandatory) {
|
||||||
{
|
|
||||||
static if (mandatory)
|
|
||||||
{
|
|
||||||
throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s",
|
throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s",
|
||||||
typeid(MemberType), typeid(Type), member), e);
|
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,
|
private void printDebugValueInjection(TypeInfo instanceType,
|
||||||
void* instanceAddress, string member, TypeInfo valueType, string key)
|
void* instanceAddress, string member, TypeInfo valueType, string key) {
|
||||||
{
|
debug {
|
||||||
debug
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s",
|
writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s",
|
||||||
key, valueType, instanceType, instanceAddress, member));
|
key, valueType, instanceType, instanceAddress, member));
|
||||||
}
|
}
|
||||||
|
@ -330,24 +272,20 @@ private void printDebugValueInjection(TypeInfo instanceType,
|
||||||
* See_Also: DependencyContainer
|
* See_Also: DependencyContainer
|
||||||
* Deprecated: Using the global container is undesired. See DependencyContainer.getInstance().
|
* 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);
|
DependencyContainer.getInstance().autowire(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowiredRegistration(RegistrationType : Object) : Registration
|
class AutowiredRegistration(RegistrationType : Object) : Registration {
|
||||||
{
|
|
||||||
private shared(DependencyContainer) container;
|
private shared(DependencyContainer) container;
|
||||||
|
|
||||||
public this(TypeInfo registeredType, InstanceFactory instanceFactory,
|
public this(TypeInfo registeredType, InstanceFactory instanceFactory,
|
||||||
shared(DependencyContainer) originatingContainer)
|
shared(DependencyContainer) originatingContainer) {
|
||||||
{
|
|
||||||
super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer);
|
super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Object getInstance(
|
public override Object getInstance(
|
||||||
InstantiationContext context = new AutowireInstantiationContext())
|
InstantiationContext context = new AutowireInstantiationContext()) {
|
||||||
{
|
|
||||||
enforce(!(originatingContainer is null),
|
enforce(!(originatingContainer is null),
|
||||||
"The registration's originating container is null. There is no way to resolve autowire dependencies.");
|
"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;
|
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!");
|
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);
|
originatingContainer.autowire(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,18 +302,14 @@ class AutowiredRegistration(RegistrationType : Object) : Registration
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void delegate() getPreDestructor(RegistrationType instance)
|
private void delegate() getPreDestructor(RegistrationType instance) {
|
||||||
{
|
|
||||||
void delegate() preDestructor = null;
|
void delegate() preDestructor = null;
|
||||||
foreach (memberName; __traits(allMembers, RegistrationType))
|
foreach (memberName; __traits(allMembers, RegistrationType)) {
|
||||||
{
|
foreach (overload; __traits(getOverloads, instance, memberName)) {
|
||||||
foreach (overload; __traits(getOverloads, instance, memberName))
|
|
||||||
{
|
|
||||||
static if (__traits(compiles, __traits(getProtection, overload))
|
static if (__traits(compiles, __traits(getProtection, overload))
|
||||||
&& __traits(getProtection, overload) == "public"
|
&& __traits(getProtection, overload) == "public"
|
||||||
&& isFunction!overload
|
&& isFunction!overload
|
||||||
&& hasUDA!(overload, PreDestroy))
|
&& hasUDA!(overload, PreDestroy)) {
|
||||||
{
|
|
||||||
preDestructor = &__traits(getMember, instance, memberName);
|
preDestructor = &__traits(getMember, instance, memberName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,7 +319,6 @@ class AutowiredRegistration(RegistrationType : Object) : Registration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowireInstantiationContext : InstantiationContext
|
class AutowireInstantiationContext : InstantiationContext {
|
||||||
{
|
|
||||||
public bool autowireInstance = true;
|
public bool autowireInstance = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,23 +26,19 @@ import std.algorithm : canFind;
|
||||||
import std.traits : fullyQualifiedName, hasUDA, BaseTypeTuple;
|
import std.traits : fullyQualifiedName, hasUDA, BaseTypeTuple;
|
||||||
import std.meta : AliasSeq;
|
import std.meta : AliasSeq;
|
||||||
|
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
import std.stdio : writeln;
|
import std.stdio : writeln;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when errors occur while resolving a type in a dependency container.
|
* Exception thrown when errors occur while resolving a type in a dependency container.
|
||||||
*/
|
*/
|
||||||
class ResolveException : Exception
|
class ResolveException : Exception {
|
||||||
{
|
this(string message, TypeInfo resolveType) {
|
||||||
this(string message, TypeInfo resolveType)
|
|
||||||
{
|
|
||||||
super(format("Exception while resolving type %s: %s", resolveType.toString(), message));
|
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);
|
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.
|
* Exception thrown when errors occur while registering a type in a dependency container.
|
||||||
*/
|
*/
|
||||||
class RegistrationException : Exception
|
class RegistrationException : Exception {
|
||||||
{
|
this(string message, TypeInfo registrationType) {
|
||||||
this(string message, TypeInfo registrationType)
|
|
||||||
{
|
|
||||||
super(format("Exception while registering type %s: %s",
|
super(format("Exception while registering type %s: %s",
|
||||||
registrationType.toString(), message));
|
registrationType.toString(), message));
|
||||||
}
|
}
|
||||||
|
@ -62,8 +56,7 @@ class RegistrationException : Exception
|
||||||
/**
|
/**
|
||||||
* Options which influence the process of registering dependencies
|
* Options which influence the process of registering dependencies
|
||||||
*/
|
*/
|
||||||
public enum RegistrationOption
|
public enum RegistrationOption {
|
||||||
{
|
|
||||||
none = 0,
|
none = 0,
|
||||||
/**
|
/**
|
||||||
* Prevent a concrete type being registered on itself. With this option you will always need
|
* Prevent a concrete type being registered on itself. With this option you will always need
|
||||||
|
@ -75,8 +68,7 @@ public enum RegistrationOption
|
||||||
/**
|
/**
|
||||||
* Options which influence the process of resolving dependencies
|
* Options which influence the process of resolving dependencies
|
||||||
*/
|
*/
|
||||||
public enum ResolveOption
|
public enum ResolveOption {
|
||||||
{
|
|
||||||
none = 0,
|
none = 0,
|
||||||
/**
|
/**
|
||||||
* Registers the type you're trying to resolve before returning it.
|
* 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
|
* 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).
|
* 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.
|
* This method is called when removeRegistration or clearAllRegistrations is called.
|
||||||
* It will also be called when the container's destructor 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.
|
* 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.
|
* You can still create new instances of this class for exceptional situations.
|
||||||
*/
|
*/
|
||||||
synchronized class DependencyContainer
|
synchronized class DependencyContainer {
|
||||||
{
|
|
||||||
private Registration[][TypeInfo] registrations;
|
private Registration[][TypeInfo] registrations;
|
||||||
|
|
||||||
private Registration[] autowireStack;
|
private Registration[] autowireStack;
|
||||||
|
@ -133,8 +122,7 @@ synchronized class DependencyContainer
|
||||||
private RegistrationOption persistentRegistrationOptions;
|
private RegistrationOption persistentRegistrationOptions;
|
||||||
private ResolveOption persistentResolveOptions;
|
private ResolveOption persistentResolveOptions;
|
||||||
|
|
||||||
~this()
|
~this() {
|
||||||
{
|
|
||||||
clearAllRegistrations();
|
clearAllRegistrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +146,7 @@ synchronized class DependencyContainer
|
||||||
*
|
*
|
||||||
* See_Also: singleInstance, newInstance, existingInstance
|
* 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);
|
return register!(ConcreteType, ConcreteType)(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,20 +169,17 @@ synchronized class DependencyContainer
|
||||||
*/
|
*/
|
||||||
public Registration register(SuperType, ConcreteType:
|
public Registration register(SuperType, ConcreteType:
|
||||||
SuperType)(RegistrationOption options = RegistrationOption.none)
|
SuperType)(RegistrationOption options = RegistrationOption.none)
|
||||||
if (!is(ConcreteType == struct))
|
if (!is(ConcreteType == struct)) {
|
||||||
{
|
|
||||||
TypeInfo registeredType = typeid(SuperType);
|
TypeInfo registeredType = typeid(SuperType);
|
||||||
TypeInfo_Class concreteType = typeid(ConcreteType);
|
TypeInfo_Class concreteType = typeid(ConcreteType);
|
||||||
|
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Register type %s (as %s)",
|
writeln(format("DEBUG: Register type %s (as %s)",
|
||||||
concreteType.toString(), registeredType.toString()));
|
concreteType.toString(), registeredType.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
||||||
if (existingRegistration)
|
if (existingRegistration) {
|
||||||
{
|
|
||||||
return existingRegistration;
|
return existingRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,11 +188,9 @@ synchronized class DependencyContainer
|
||||||
instanceFactory, this);
|
instanceFactory, this);
|
||||||
newRegistration.initializeFactoryType().singleInstance();
|
newRegistration.initializeFactoryType().singleInstance();
|
||||||
|
|
||||||
static if (!is(SuperType == ConcreteType))
|
static if (!is(SuperType == ConcreteType)) {
|
||||||
{
|
|
||||||
if (!hasOption(options, persistentRegistrationOptions,
|
if (!hasOption(options, persistentRegistrationOptions,
|
||||||
RegistrationOption.doNotAddConcreteTypeRegistration))
|
RegistrationOption.doNotAddConcreteTypeRegistration)) {
|
||||||
{
|
|
||||||
auto concreteTypeRegistration = register!ConcreteType;
|
auto concreteTypeRegistration = register!ConcreteType;
|
||||||
concreteTypeRegistration.linkTo(newRegistration);
|
concreteTypeRegistration.linkTo(newRegistration);
|
||||||
}
|
}
|
||||||
|
@ -219,38 +201,30 @@ synchronized class DependencyContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool hasOption(OptionType)(OptionType options,
|
private bool hasOption(OptionType)(OptionType options,
|
||||||
OptionType persistentOptions, OptionType option)
|
OptionType persistentOptions, OptionType option) {
|
||||||
{
|
|
||||||
return ((options | persistentOptions) & option) != 0;
|
return ((options | persistentOptions) & option) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OptionType buildFlags(OptionType)(OptionType[] options)
|
private OptionType buildFlags(OptionType)(OptionType[] options) {
|
||||||
{
|
|
||||||
OptionType flags;
|
OptionType flags;
|
||||||
foreach (option; options)
|
foreach (option; options) {
|
||||||
{
|
|
||||||
flags |= option;
|
flags |= option;
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType)
|
private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) {
|
||||||
{
|
|
||||||
auto existingCandidates = registrationType in registrations;
|
auto existingCandidates = registrationType in registrations;
|
||||||
if (existingCandidates)
|
if (existingCandidates) {
|
||||||
{
|
|
||||||
return getRegistration(cast(Registration[])*existingCandidates, qualifierType);
|
return getRegistration(cast(Registration[])*existingCandidates, qualifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType)
|
private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) {
|
||||||
{
|
foreach (existingRegistration; candidates) {
|
||||||
foreach (existingRegistration; candidates)
|
if (existingRegistration.instanceType == concreteType) {
|
||||||
{
|
|
||||||
if (existingRegistration.instanceType == concreteType)
|
|
||||||
{
|
|
||||||
return existingRegistration;
|
return existingRegistration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,8 +273,7 @@ synchronized class DependencyContainer
|
||||||
*/
|
*/
|
||||||
public RegistrationType resolve(RegistrationType)(
|
public RegistrationType resolve(RegistrationType)(
|
||||||
ResolveOption resolveOptions = ResolveOption.none)
|
ResolveOption resolveOptions = ResolveOption.none)
|
||||||
if (!is(RegistrationType == struct))
|
if (!is(RegistrationType == struct)) {
|
||||||
{
|
|
||||||
return resolve!(RegistrationType, RegistrationType)(resolveOptions);
|
return resolve!(RegistrationType, RegistrationType)(resolveOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,32 +305,26 @@ synchronized class DependencyContainer
|
||||||
*/
|
*/
|
||||||
public QualifierType resolve(RegistrationType, QualifierType:
|
public QualifierType resolve(RegistrationType, QualifierType:
|
||||||
RegistrationType)(ResolveOption resolveOptions = ResolveOption.none)
|
RegistrationType)(ResolveOption resolveOptions = ResolveOption.none)
|
||||||
if (!is(QualifierType == struct))
|
if (!is(QualifierType == struct)) {
|
||||||
{
|
|
||||||
TypeInfo resolveType = typeid(RegistrationType);
|
TypeInfo resolveType = typeid(RegistrationType);
|
||||||
TypeInfo qualifierType = typeid(QualifierType);
|
TypeInfo qualifierType = typeid(QualifierType);
|
||||||
|
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString());
|
writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto candidates = resolveType in registrations;
|
auto candidates = resolveType in registrations;
|
||||||
if (!candidates)
|
if (!candidates) {
|
||||||
{
|
static if (is(typeof(typeid(QualifierType)) == TypeInfo_Class) && !__traits(isAbstractClass, QualifierType)) {
|
||||||
static if (is(typeof(typeid(QualifierType)) == TypeInfo_Class) && !__traits(isAbstractClass, QualifierType))
|
|
||||||
{
|
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption
|
if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption
|
||||||
.registerBeforeResolving))
|
.registerBeforeResolving)) {
|
||||||
{
|
|
||||||
register!(RegistrationType, QualifierType)();
|
register!(RegistrationType, QualifierType)();
|
||||||
return resolve!(RegistrationType, QualifierType)(resolveOptions);
|
return resolve!(RegistrationType, QualifierType)(resolveOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions,
|
if (hasOption(resolveOptions, persistentResolveOptions,
|
||||||
ResolveOption.noResolveException))
|
ResolveOption.noResolveException)) {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,37 +334,29 @@ synchronized class DependencyContainer
|
||||||
Registration registration = getQualifiedRegistration(resolveType,
|
Registration registration = getQualifiedRegistration(resolveType,
|
||||||
qualifierType, cast(Registration[])*candidates);
|
qualifierType, cast(Registration[])*candidates);
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
|
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
|
||||||
callPostConstructors(newInstance);
|
callPostConstructors(newInstance);
|
||||||
return newInstance;
|
return newInstance;
|
||||||
}
|
} catch (ValueInjectionException e) {
|
||||||
catch (ValueInjectionException e)
|
|
||||||
{
|
|
||||||
throw new ResolveException(e, resolveType);
|
throw new ResolveException(e, resolveType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRegistered(RegistrationType)()
|
bool isRegistered(RegistrationType)() {
|
||||||
{
|
|
||||||
TypeInfo typeInfo = typeid(RegistrationType);
|
TypeInfo typeInfo = typeid(RegistrationType);
|
||||||
auto candidates = typeInfo in registrations;
|
auto candidates = typeInfo in registrations;
|
||||||
return candidates !is null;
|
return candidates !is null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration)
|
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
|
||||||
{
|
|
||||||
QualifierType instance;
|
QualifierType instance;
|
||||||
if (!(cast(Registration[]) autowireStack).canFind(registration))
|
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
|
||||||
{
|
|
||||||
autowireStack ~= cast(shared(Registration)) registration;
|
autowireStack ~= cast(shared(Registration)) registration;
|
||||||
instance = cast(QualifierType) registration.getInstance(
|
instance = cast(QualifierType) registration.getInstance(
|
||||||
new AutowireInstantiationContext());
|
new AutowireInstantiationContext());
|
||||||
autowireStack = autowireStack[0 .. $ - 1];
|
autowireStack = autowireStack[0 .. $ - 1];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
auto autowireContext = new AutowireInstantiationContext();
|
auto autowireContext = new AutowireInstantiationContext();
|
||||||
autowireContext.autowireInstance = false;
|
autowireContext.autowireInstance = false;
|
||||||
instance = cast(QualifierType) registration.getInstance(autowireContext);
|
instance = cast(QualifierType) registration.getInstance(autowireContext);
|
||||||
|
@ -423,25 +382,21 @@ synchronized class DependencyContainer
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
public RegistrationType[] resolveAll(RegistrationType)(
|
public RegistrationType[] resolveAll(RegistrationType)(
|
||||||
ResolveOption resolveOptions = ResolveOption.none)
|
ResolveOption resolveOptions = ResolveOption.none) {
|
||||||
{
|
|
||||||
RegistrationType[] instances;
|
RegistrationType[] instances;
|
||||||
TypeInfo resolveType = typeid(RegistrationType);
|
TypeInfo resolveType = typeid(RegistrationType);
|
||||||
|
|
||||||
auto qualifiedRegistrations = resolveType in registrations;
|
auto qualifiedRegistrations = resolveType in registrations;
|
||||||
if (!qualifiedRegistrations)
|
if (!qualifiedRegistrations) {
|
||||||
{
|
|
||||||
if (hasOption(resolveOptions, persistentResolveOptions,
|
if (hasOption(resolveOptions, persistentResolveOptions,
|
||||||
ResolveOption.noResolveException))
|
ResolveOption.noResolveException)) {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ResolveException("Type not registered.", resolveType);
|
throw new ResolveException("Type not registered.", resolveType);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (registration; cast(Registration[])*qualifiedRegistrations)
|
foreach (registration; cast(Registration[])*qualifiedRegistrations) {
|
||||||
{
|
|
||||||
instances ~= resolveAutowiredInstance!RegistrationType(registration);
|
instances ~= resolveAutowiredInstance!RegistrationType(registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,12 +404,9 @@ synchronized class DependencyContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registration getQualifiedRegistration(TypeInfo resolveType,
|
private Registration getQualifiedRegistration(TypeInfo resolveType,
|
||||||
TypeInfo qualifierType, Registration[] candidates)
|
TypeInfo qualifierType, Registration[] candidates) {
|
||||||
{
|
if (resolveType == qualifierType) {
|
||||||
if (resolveType == qualifierType)
|
if (candidates.length > 1) {
|
||||||
{
|
|
||||||
if (candidates.length > 1)
|
|
||||||
{
|
|
||||||
string candidateList = candidates.toConcreteTypeListString();
|
string candidateList = candidates.toConcreteTypeListString();
|
||||||
throw new ResolveException(
|
throw new ResolveException(
|
||||||
"Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.",
|
"Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.",
|
||||||
|
@ -467,17 +419,13 @@ synchronized class DependencyContainer
|
||||||
return getRegistration(candidates, qualifierType);
|
return getRegistration(candidates, qualifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callPostConstructors(Type)(Type instance)
|
private void callPostConstructors(Type)(Type instance) {
|
||||||
{
|
foreach (memberName; __traits(allMembers, Type)) {
|
||||||
foreach (memberName; __traits(allMembers, Type))
|
foreach (overload; __traits(getOverloads, instance, memberName)) {
|
||||||
{
|
|
||||||
foreach (overload; __traits(getOverloads, instance, memberName))
|
|
||||||
{
|
|
||||||
static if (__traits(compiles, __traits(getProtection, overload))
|
static if (__traits(compiles, __traits(getProtection, overload))
|
||||||
&& __traits(getProtection, overload) == "public"
|
&& __traits(getProtection, overload) == "public"
|
||||||
&& isFunction!overload
|
&& isFunction!overload
|
||||||
&& hasUDA!(overload, PostConstruct))
|
&& hasUDA!(overload, PostConstruct)) {
|
||||||
{
|
|
||||||
__traits(getMember, instance, memberName)();
|
__traits(getMember, instance, memberName)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,10 +435,8 @@ synchronized class DependencyContainer
|
||||||
/**
|
/**
|
||||||
* Clears all dependency registrations managed by this container.
|
* Clears all dependency registrations managed by this container.
|
||||||
*/
|
*/
|
||||||
public void clearAllRegistrations()
|
public void clearAllRegistrations() {
|
||||||
{
|
foreach (registrationsOfType; registrations) {
|
||||||
foreach (registrationsOfType; registrations)
|
|
||||||
{
|
|
||||||
callPreDestructorsOfRegistrations(registrationsOfType);
|
callPreDestructorsOfRegistrations(registrationsOfType);
|
||||||
}
|
}
|
||||||
registrations.destroy();
|
registrations.destroy();
|
||||||
|
@ -506,20 +452,16 @@ synchronized class DependencyContainer
|
||||||
* container.removeRegistration!Animal;
|
* container.removeRegistration!Animal;
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
public void removeRegistration(RegistrationType)()
|
public void removeRegistration(RegistrationType)() {
|
||||||
{
|
|
||||||
auto registrationsOfType = *(typeid(RegistrationType) in registrations);
|
auto registrationsOfType = *(typeid(RegistrationType) in registrations);
|
||||||
callPreDestructorsOfRegistrations(registrationsOfType);
|
callPreDestructorsOfRegistrations(registrationsOfType);
|
||||||
registrations.remove(typeid(RegistrationType));
|
registrations.remove(typeid(RegistrationType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations)
|
private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) {
|
||||||
{
|
foreach (registration; registrations) {
|
||||||
foreach (registration; registrations)
|
|
||||||
{
|
|
||||||
Registration unsharedRegistration = cast(Registration) registration;
|
Registration unsharedRegistration = cast(Registration) registration;
|
||||||
if (unsharedRegistration.preDestructor !is null)
|
if (unsharedRegistration.preDestructor !is null) {
|
||||||
{
|
|
||||||
unsharedRegistration.preDestructor()();
|
unsharedRegistration.preDestructor()();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,32 +470,28 @@ synchronized class DependencyContainer
|
||||||
/**
|
/**
|
||||||
* Apply persistent registration options which will be used everytime register() is called.
|
* Apply persistent registration options which will be used everytime register() is called.
|
||||||
*/
|
*/
|
||||||
public void setPersistentRegistrationOptions(RegistrationOption options)
|
public void setPersistentRegistrationOptions(RegistrationOption options) {
|
||||||
{
|
|
||||||
persistentRegistrationOptions = options;
|
persistentRegistrationOptions = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsets all applied persistent registration options
|
* Unsets all applied persistent registration options
|
||||||
*/
|
*/
|
||||||
public void unsetPersistentRegistrationOptions()
|
public void unsetPersistentRegistrationOptions() {
|
||||||
{
|
|
||||||
persistentRegistrationOptions = RegistrationOption.none;
|
persistentRegistrationOptions = RegistrationOption.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply persistent resolve options which will be used everytime resolve() is called.
|
* Apply persistent resolve options which will be used everytime resolve() is called.
|
||||||
*/
|
*/
|
||||||
public void setPersistentResolveOptions(ResolveOption options)
|
public void setPersistentResolveOptions(ResolveOption options) {
|
||||||
{
|
|
||||||
persistentResolveOptions = options;
|
persistentResolveOptions = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsets all applied persistent resolve options
|
* Unsets all applied persistent resolve options
|
||||||
*/
|
*/
|
||||||
public void unsetPersistentResolveOptions()
|
public void unsetPersistentResolveOptions() {
|
||||||
{
|
|
||||||
persistentResolveOptions = ResolveOption.none;
|
persistentResolveOptions = ResolveOption.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,8 @@ import poodinis.autowire : autowire;
|
||||||
|
|
||||||
import std.traits : hasUDA, ReturnType;
|
import std.traits : hasUDA, ReturnType;
|
||||||
|
|
||||||
class ApplicationContext
|
class ApplicationContext {
|
||||||
{
|
public void registerDependencies(shared(DependencyContainer) container) {
|
||||||
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
|
* A component annotation is used for specifying which factory methods produce components in
|
||||||
* an application context.
|
* an application context.
|
||||||
*/
|
*/
|
||||||
struct Component
|
struct Component {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation allows you to specify by which super type the component should be registered. This
|
* 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.
|
* enables you to use type-qualified alternatives for dependencies.
|
||||||
*/
|
*/
|
||||||
struct RegisterByType(Type)
|
struct RegisterByType(Type) {
|
||||||
{
|
|
||||||
Type type;
|
Type type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +44,7 @@ struct RegisterByType(Type)
|
||||||
* Components with the prototype registration will be scoped as dependencies which will create
|
* 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.
|
* 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
|
* 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.
|
* 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();
|
auto context = new Context();
|
||||||
context.registerDependencies(container);
|
context.registerDependencies(container);
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -69,33 +63,24 @@ public void registerContext(Context : ApplicationContext)(shared(DependencyConta
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerContextComponents(ApplicationContextType : ApplicationContext)(
|
public void registerContextComponents(ApplicationContextType : ApplicationContext)(
|
||||||
ApplicationContextType context, shared(DependencyContainer) container)
|
ApplicationContextType context, shared(DependencyContainer) container) {
|
||||||
{
|
foreach (memberName; __traits(allMembers, ApplicationContextType)) {
|
||||||
foreach (memberName; __traits(allMembers, ApplicationContextType))
|
foreach (overload; __traits(getOverloads, context, memberName)) {
|
||||||
{
|
static if (__traits(getProtection, overload) == "public" && hasUDA!(overload, Component)) {
|
||||||
foreach (overload; __traits(getOverloads, context, memberName))
|
|
||||||
{
|
|
||||||
static if (__traits(getProtection, overload) == "public" && hasUDA!(overload, Component))
|
|
||||||
{
|
|
||||||
auto factoryMethod = &__traits(getMember, context, memberName);
|
auto factoryMethod = &__traits(getMember, context, memberName);
|
||||||
Registration registration = null;
|
Registration registration = null;
|
||||||
auto createsSingleton = CreatesSingleton.yes;
|
auto createsSingleton = CreatesSingleton.yes;
|
||||||
|
|
||||||
foreach (attribute; __traits(getAttributes, overload))
|
foreach (attribute; __traits(getAttributes, overload)) {
|
||||||
{
|
static if (is(attribute == RegisterByType!T, T)) {
|
||||||
static if (is(attribute == RegisterByType!T, T))
|
|
||||||
{
|
|
||||||
registration = container.register!(typeof(attribute.type),
|
registration = container.register!(typeof(attribute.type),
|
||||||
ReturnType!factoryMethod);
|
ReturnType!factoryMethod);
|
||||||
}
|
} else static if (__traits(isSame, attribute, Prototype)) {
|
||||||
else static if (__traits(isSame, attribute, Prototype))
|
|
||||||
{
|
|
||||||
createsSingleton = CreatesSingleton.no;
|
createsSingleton = CreatesSingleton.no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registration is null)
|
if (registration is null) {
|
||||||
{
|
|
||||||
registration = container.register!(ReturnType!factoryMethod);
|
registration = container.register!(ReturnType!factoryMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,7 @@ import std.exception : enforce;
|
||||||
import std.traits : Parameters, isBuiltinType, fullyQualifiedName;
|
import std.traits : Parameters, isBuiltinType, fullyQualifiedName;
|
||||||
import std.string : format;
|
import std.string : format;
|
||||||
|
|
||||||
debug
|
debug {
|
||||||
{
|
|
||||||
import std.stdio : writeln;
|
import std.stdio : writeln;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,42 +27,34 @@ alias CreatesSingleton = Flag!"CreatesSingleton";
|
||||||
alias InstanceFactoryMethod = Object delegate();
|
alias InstanceFactoryMethod = Object delegate();
|
||||||
alias InstanceEventHandler = void delegate(Object instance);
|
alias InstanceEventHandler = void delegate(Object instance);
|
||||||
|
|
||||||
class InstanceCreationException : Exception
|
class InstanceCreationException : Exception {
|
||||||
{
|
this(string message, string file = __FILE__, size_t line = __LINE__) {
|
||||||
this(string message, string file = __FILE__, size_t line = __LINE__)
|
|
||||||
{
|
|
||||||
super(message, file, line);
|
super(message, file, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstanceFactoryParameters
|
struct InstanceFactoryParameters {
|
||||||
{
|
|
||||||
TypeInfo_Class instanceType;
|
TypeInfo_Class instanceType;
|
||||||
CreatesSingleton createsSingleton = CreatesSingleton.yes;
|
CreatesSingleton createsSingleton = CreatesSingleton.yes;
|
||||||
Object existingInstance;
|
Object existingInstance;
|
||||||
InstanceFactoryMethod factoryMethod;
|
InstanceFactoryMethod factoryMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstanceFactory
|
class InstanceFactory {
|
||||||
{
|
|
||||||
private Object instance = null;
|
private Object instance = null;
|
||||||
private InstanceFactoryParameters _factoryParameters;
|
private InstanceFactoryParameters _factoryParameters;
|
||||||
private InstanceEventHandler _constructionHandler;
|
private InstanceEventHandler _constructionHandler;
|
||||||
|
|
||||||
this()
|
this() {
|
||||||
{
|
|
||||||
factoryParameters = InstanceFactoryParameters();
|
factoryParameters = InstanceFactoryParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property void factoryParameters(InstanceFactoryParameters factoryParameters)
|
public @property void factoryParameters(InstanceFactoryParameters factoryParameters) {
|
||||||
{
|
if (factoryParameters.factoryMethod is null) {
|
||||||
if (factoryParameters.factoryMethod is null)
|
|
||||||
{
|
|
||||||
factoryParameters.factoryMethod = &this.createInstance;
|
factoryParameters.factoryMethod = &this.createInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (factoryParameters.existingInstance !is null)
|
if (factoryParameters.existingInstance !is null) {
|
||||||
{
|
|
||||||
factoryParameters.createsSingleton = CreatesSingleton.yes;
|
factoryParameters.createsSingleton = CreatesSingleton.yes;
|
||||||
this.instance = factoryParameters.existingInstance;
|
this.instance = factoryParameters.existingInstance;
|
||||||
}
|
}
|
||||||
|
@ -71,99 +62,76 @@ class InstanceFactory
|
||||||
_factoryParameters = factoryParameters;
|
_factoryParameters = factoryParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property InstanceFactoryParameters factoryParameters()
|
public @property InstanceFactoryParameters factoryParameters() {
|
||||||
{
|
|
||||||
return _factoryParameters;
|
return _factoryParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInstance()
|
public Object getInstance() {
|
||||||
{
|
if (_factoryParameters.createsSingleton && instance !is null) {
|
||||||
if (_factoryParameters.createsSingleton && instance !is null)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
debug (poodinisVerbose)
|
|
||||||
{
|
|
||||||
printDebugUseExistingInstance();
|
printDebugUseExistingInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug (poodinisVerbose)
|
debug (poodinisVerbose) {
|
||||||
{
|
|
||||||
printDebugCreateNewInstance();
|
printDebugCreateNewInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
instance = _factoryParameters.factoryMethod();
|
instance = _factoryParameters.factoryMethod();
|
||||||
if (_constructionHandler !is null)
|
if (_constructionHandler !is null) {
|
||||||
{
|
|
||||||
_constructionHandler(instance);
|
_constructionHandler(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onConstructed(InstanceEventHandler handler)
|
void onConstructed(InstanceEventHandler handler) {
|
||||||
{
|
|
||||||
_constructionHandler = handler;
|
_constructionHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugUseExistingInstance()
|
private void printDebugUseExistingInstance() {
|
||||||
{
|
debug {
|
||||||
debug
|
if (_factoryParameters.instanceType !is null) {
|
||||||
{
|
|
||||||
if (_factoryParameters.instanceType !is null)
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Existing instance returned of type %s",
|
writeln(format("DEBUG: Existing instance returned of type %s",
|
||||||
_factoryParameters.instanceType.toString()));
|
_factoryParameters.instanceType.toString()));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeln("DEBUG: Existing instance returned from custom factory method");
|
writeln("DEBUG: Existing instance returned from custom factory method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printDebugCreateNewInstance()
|
private void printDebugCreateNewInstance() {
|
||||||
{
|
debug {
|
||||||
debug
|
if (_factoryParameters.instanceType !is null) {
|
||||||
{
|
|
||||||
if (_factoryParameters.instanceType !is null)
|
|
||||||
{
|
|
||||||
writeln(format("DEBUG: Creating new instance of type %s",
|
writeln(format("DEBUG: Creating new instance of type %s",
|
||||||
_factoryParameters.instanceType.toString()));
|
_factoryParameters.instanceType.toString()));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeln("DEBUG: Creating new instance from custom factory method");
|
writeln("DEBUG: Creating new instance from custom factory method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object createInstance()
|
protected Object createInstance() {
|
||||||
{
|
|
||||||
enforce!InstanceCreationException(_factoryParameters.instanceType,
|
enforce!InstanceCreationException(_factoryParameters.instanceType,
|
||||||
"Instance type is not defined, cannot create instance without knowing its type.");
|
"Instance type is not defined, cannot create instance without knowing its type.");
|
||||||
return _factoryParameters.instanceType.create();
|
return _factoryParameters.instanceType.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
|
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
||||||
{
|
|
||||||
private shared DependencyContainer container;
|
private shared DependencyContainer container;
|
||||||
private bool isBeingInjected = false;
|
private bool isBeingInjected = false;
|
||||||
|
|
||||||
this(shared DependencyContainer container)
|
this(shared DependencyContainer container) {
|
||||||
{
|
|
||||||
this.container = container;
|
this.container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createArgumentList(Params...)()
|
private static string createArgumentList(Params...)() {
|
||||||
{
|
|
||||||
string argumentList = "";
|
string argumentList = "";
|
||||||
foreach (param; Params)
|
foreach (param; Params) {
|
||||||
{
|
if (argumentList.length > 0) {
|
||||||
if (argumentList.length > 0)
|
|
||||||
{
|
|
||||||
argumentList ~= ",";
|
argumentList ~= ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,23 +140,18 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
|
||||||
return argumentList;
|
return argumentList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string createImportList(Params...)()
|
private static string createImportList(Params...)() {
|
||||||
{
|
|
||||||
string importList = "";
|
string importList = "";
|
||||||
foreach (param; Params)
|
foreach (param; Params) {
|
||||||
{
|
|
||||||
importList ~= createImportsString!param;
|
importList ~= createImportsString!param;
|
||||||
}
|
}
|
||||||
return importList;
|
return importList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool parametersAreValid(Params...)()
|
private static bool parametersAreValid(Params...)() {
|
||||||
{
|
|
||||||
bool isValid = true;
|
bool isValid = true;
|
||||||
foreach (param; Params)
|
foreach (param; Params) {
|
||||||
{
|
if (isBuiltinType!param || is(param == struct)) {
|
||||||
if (isBuiltinType!param || is(param == struct))
|
|
||||||
{
|
|
||||||
isValid = false;
|
isValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -197,26 +160,23 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Object createInstance()
|
protected override Object createInstance() {
|
||||||
{
|
|
||||||
enforce!InstanceCreationException(container,
|
enforce!InstanceCreationException(container,
|
||||||
"A dependency container is not defined. Cannot perform constructor injection without one.");
|
"A dependency container is not defined. Cannot perform constructor injection without one.");
|
||||||
enforce!InstanceCreationException(!isBeingInjected,
|
enforce!InstanceCreationException(!isBeingInjected,
|
||||||
format("%s is already being created and injected; possible circular dependencies in constructors?",
|
format("%s is already being created and injected; possible circular dependencies in constructors?",
|
||||||
InstanceType.stringof));
|
InstanceType.stringof));
|
||||||
|
|
||||||
Object instance = null;
|
Object instance = null;
|
||||||
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`)))
|
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
||||||
{
|
foreach (ctor; __traits(getOverloads, InstanceType, `__ctor`)) {
|
||||||
foreach (ctor; __traits(getOverloads, InstanceType, `__ctor`))
|
static if (parametersAreValid!(Parameters!ctor)) {
|
||||||
{
|
|
||||||
static if (parametersAreValid!(Parameters!ctor))
|
|
||||||
{
|
|
||||||
isBeingInjected = true;
|
isBeingInjected = true;
|
||||||
mixin(createImportsString!InstanceType ~ createImportList!(
|
mixin(createImportsString!InstanceType ~ createImportList!(
|
||||||
Parameters!ctor) ~ `
|
Parameters!ctor) ~ `
|
||||||
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(
|
instance = new `
|
||||||
Parameters!ctor) ~ `);
|
~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(
|
||||||
|
Parameters!ctor) ~ `);
|
||||||
`);
|
`);
|
||||||
isBeingInjected = false;
|
isBeingInjected = false;
|
||||||
break;
|
break;
|
||||||
|
@ -224,13 +184,12 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance is null)
|
if (instance is null) {
|
||||||
{
|
|
||||||
instance = typeid(InstanceType).create();
|
instance = typeid(InstanceType).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce!InstanceCreationException(instance !is null,
|
enforce!InstanceCreationException(instance !is null,
|
||||||
"Unable to create instance of type" ~ InstanceType.stringof
|
"Unable to create instance of type" ~ InstanceType.stringof
|
||||||
~ ", does it have injectable constructors?");
|
~ ", does it have injectable constructors?");
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
|
|
|
@ -14,16 +14,12 @@ module poodinis.imports;
|
||||||
import std.meta : staticIndexOf;
|
import std.meta : staticIndexOf;
|
||||||
import std.traits : moduleName, TemplateArgsOf, isBuiltinType, isType;
|
import std.traits : moduleName, TemplateArgsOf, isBuiltinType, isType;
|
||||||
|
|
||||||
public static string createImportsString(Type, ParentTypeList...)()
|
public static string createImportsString(Type, ParentTypeList...)() {
|
||||||
{
|
|
||||||
string imports = `import ` ~ moduleName!Type ~ `;`;
|
string imports = `import ` ~ moduleName!Type ~ `;`;
|
||||||
static if (__traits(compiles, TemplateArgsOf!Type))
|
static if (__traits(compiles, TemplateArgsOf!Type)) {
|
||||||
{
|
foreach (TemplateArgType; TemplateArgsOf!Type) {
|
||||||
foreach (TemplateArgType; TemplateArgsOf!Type)
|
|
||||||
{
|
|
||||||
static if (isType!TemplateArgType &&
|
static if (isType!TemplateArgType &&
|
||||||
(!isBuiltinType!TemplateArgType && staticIndexOf!(TemplateArgType, ParentTypeList) == -1))
|
(!isBuiltinType!TemplateArgType && staticIndexOf!(TemplateArgType, ParentTypeList) == -1)) {
|
||||||
{
|
|
||||||
imports ~= createImportsString!(TemplateArgType, ParentTypeList, Type);
|
imports ~= createImportsString!(TemplateArgType, ParentTypeList, Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,8 @@ module poodinis.polyfill;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
static if (!__traits(compiles, basicExceptionCtors))
|
static if (!__traits(compiles, basicExceptionCtors)) {
|
||||||
{
|
mixin template basicExceptionCtors() {
|
||||||
mixin template basicExceptionCtors()
|
|
||||||
{
|
|
||||||
/++
|
/++
|
||||||
Params:
|
Params:
|
||||||
msg = The message for the exception.
|
msg = The message for the exception.
|
||||||
|
@ -38,8 +36,7 @@ static if (!__traits(compiles, basicExceptionCtors))
|
||||||
line = The line number where the exception occurred.
|
line = The line number where the exception occurred.
|
||||||
next = The previous exception in the chain of exceptions, if any.
|
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);
|
super(msg, file, line, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +47,10 @@ static if (!__traits(compiles, basicExceptionCtors))
|
||||||
file = The file where the exception occurred.
|
file = The file where the exception occurred.
|
||||||
line = The line number 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);
|
super(msg, file, line, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
public import std.exception : basicExceptionCtors;
|
public import std.exception : basicExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ import poodinis.container : DependencyContainer;
|
||||||
import poodinis.factory : InstanceFactory, InstanceEventHandler,
|
import poodinis.factory : InstanceFactory, InstanceEventHandler,
|
||||||
InstanceCreationException, InstanceFactoryParameters, CreatesSingleton;
|
InstanceCreationException, InstanceFactoryParameters, CreatesSingleton;
|
||||||
|
|
||||||
class Registration
|
class Registration {
|
||||||
{
|
|
||||||
private TypeInfo _registeredType = null;
|
private TypeInfo _registeredType = null;
|
||||||
private TypeInfo_Class _instanceType = null;
|
private TypeInfo_Class _instanceType = null;
|
||||||
private Registration linkedRegistration;
|
private Registration linkedRegistration;
|
||||||
|
@ -26,82 +25,68 @@ class Registration
|
||||||
private InstanceFactory _instanceFactory;
|
private InstanceFactory _instanceFactory;
|
||||||
private void delegate() _preDestructor;
|
private void delegate() _preDestructor;
|
||||||
|
|
||||||
public @property registeredType()
|
public @property registeredType() {
|
||||||
{
|
|
||||||
return _registeredType;
|
return _registeredType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property instanceType()
|
public @property instanceType() {
|
||||||
{
|
|
||||||
return _instanceType;
|
return _instanceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property originatingContainer()
|
public @property originatingContainer() {
|
||||||
{
|
|
||||||
return _originatingContainer;
|
return _originatingContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property instanceFactory()
|
public @property instanceFactory() {
|
||||||
{
|
|
||||||
return _instanceFactory;
|
return _instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property preDestructor()
|
public @property preDestructor() {
|
||||||
{
|
|
||||||
return _preDestructor;
|
return _preDestructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @property preDestructor(void delegate() preDestructor)
|
protected @property preDestructor(void delegate() preDestructor) {
|
||||||
{
|
|
||||||
_preDestructor = preDestructor;
|
_preDestructor = preDestructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(TypeInfo registeredType, TypeInfo_Class instanceType,
|
this(TypeInfo registeredType, TypeInfo_Class instanceType,
|
||||||
InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer)
|
InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) {
|
||||||
{
|
|
||||||
this._registeredType = registeredType;
|
this._registeredType = registeredType;
|
||||||
this._instanceType = instanceType;
|
this._instanceType = instanceType;
|
||||||
this._originatingContainer = originatingContainer;
|
this._originatingContainer = originatingContainer;
|
||||||
this._instanceFactory = instanceFactory;
|
this._instanceFactory = instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInstance(InstantiationContext context = new InstantiationContext())
|
public Object getInstance(InstantiationContext context = new InstantiationContext()) {
|
||||||
{
|
if (linkedRegistration !is null) {
|
||||||
if (linkedRegistration !is null)
|
|
||||||
{
|
|
||||||
return linkedRegistration.getInstance(context);
|
return linkedRegistration.getInstance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instanceFactory is null)
|
if (instanceFactory is null) {
|
||||||
{
|
|
||||||
throw new InstanceCreationException(
|
throw new InstanceCreationException(
|
||||||
"No instance factory defined for registration of type " ~ registeredType.toString());
|
"No instance factory defined for registration of type " ~ registeredType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return instanceFactory.getInstance();
|
return instanceFactory.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Registration linkTo(Registration registration)
|
public Registration linkTo(Registration registration) {
|
||||||
{
|
|
||||||
this.linkedRegistration = registration;
|
this.linkedRegistration = registration;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Registration onConstructed(InstanceEventHandler handler)
|
Registration onConstructed(InstanceEventHandler handler) {
|
||||||
{
|
|
||||||
if (instanceFactory !is null)
|
if (instanceFactory !is null)
|
||||||
instanceFactory.onConstructed(handler);
|
instanceFactory.onConstructed(handler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstanceFactoryParameters copyFactoryParameters(Registration registration)
|
private InstanceFactoryParameters copyFactoryParameters(Registration registration) {
|
||||||
{
|
|
||||||
return registration.instanceFactory.factoryParameters;
|
return registration.instanceFactory.factoryParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFactoryParameters(Registration registration, InstanceFactoryParameters newParameters)
|
private void setFactoryParameters(Registration registration, InstanceFactoryParameters newParameters) {
|
||||||
{
|
|
||||||
registration.instanceFactory.factoryParameters = 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.
|
* 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();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.instanceType = registration.instanceType;
|
params.instanceType = registration.instanceType;
|
||||||
registration.setFactoryParameters(params);
|
registration.setFactoryParameters(params);
|
||||||
|
@ -123,8 +107,7 @@ public Registration initializeFactoryType(Registration registration)
|
||||||
*
|
*
|
||||||
* Effectively makes the given registration a singleton.
|
* Effectively makes the given registration a singleton.
|
||||||
*/
|
*/
|
||||||
public Registration singleInstance(Registration registration)
|
public Registration singleInstance(Registration registration) {
|
||||||
{
|
|
||||||
auto params = registration.copyFactoryParameters();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.createsSingleton = CreatesSingleton.yes;
|
params.createsSingleton = CreatesSingleton.yes;
|
||||||
registration.setFactoryParameters(params);
|
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.
|
* 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();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.createsSingleton = CreatesSingleton.no;
|
params.createsSingleton = CreatesSingleton.no;
|
||||||
params.existingInstance = null;
|
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.
|
* 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();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.createsSingleton = CreatesSingleton.yes;
|
params.createsSingleton = CreatesSingleton.yes;
|
||||||
params.existingInstance = instance;
|
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.
|
* Scopes registrations to create new instances using the given initializer delegate.
|
||||||
*/
|
*/
|
||||||
public Registration initializedBy(T)(Registration registration, T delegate() initializer)
|
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();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.createsSingleton = CreatesSingleton.no;
|
params.createsSingleton = CreatesSingleton.no;
|
||||||
params.factoryMethod = () => cast(Object) initializer();
|
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.
|
* 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();
|
auto params = registration.copyFactoryParameters();
|
||||||
params.createsSingleton = CreatesSingleton.yes;
|
params.createsSingleton = CreatesSingleton.yes;
|
||||||
params.factoryMethod = () => cast(Object) initializer();
|
params.factoryMethod = () => cast(Object) initializer();
|
||||||
|
@ -180,13 +159,10 @@ public Registration initializedOnceBy(T : Object)(Registration registration, T d
|
||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string toConcreteTypeListString(Registration[] registrations)
|
public string toConcreteTypeListString(Registration[] registrations) {
|
||||||
{
|
|
||||||
auto concreteTypeListString = "";
|
auto concreteTypeListString = "";
|
||||||
foreach (registration; registrations)
|
foreach (registration; registrations) {
|
||||||
{
|
if (concreteTypeListString.length > 0) {
|
||||||
if (concreteTypeListString.length > 0)
|
|
||||||
{
|
|
||||||
concreteTypeListString ~= ", ";
|
concreteTypeListString ~= ", ";
|
||||||
}
|
}
|
||||||
concreteTypeListString ~= registration.instanceType.toString();
|
concreteTypeListString ~= registration.instanceType.toString();
|
||||||
|
@ -194,6 +170,5 @@ public string toConcreteTypeListString(Registration[] registrations)
|
||||||
return concreteTypeListString;
|
return concreteTypeListString;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstantiationContext
|
class InstantiationContext {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,19 @@ import std.string : format;
|
||||||
/**
|
/**
|
||||||
* Thrown when something goes wrong during value injection.
|
* Thrown when something goes wrong during value injection.
|
||||||
*/
|
*/
|
||||||
class ValueInjectionException : Exception
|
class ValueInjectionException : Exception {
|
||||||
{
|
|
||||||
mixin basicExceptionCtors;
|
mixin basicExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown by injectors when the value with the given key cannot be found.
|
* Thrown by injectors when the value with the given key cannot be found.
|
||||||
*/
|
*/
|
||||||
class ValueNotAvailableException : Exception
|
class ValueNotAvailableException : Exception {
|
||||||
{
|
this(string key) {
|
||||||
this(string key)
|
|
||||||
{
|
|
||||||
super(format("Value for key %s is not available", 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);
|
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.
|
* 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.
|
* The textual key used to find the value by injectors.
|
||||||
*
|
*
|
||||||
|
@ -115,8 +109,7 @@ struct MandatoryValue
|
||||||
* container.register!(ValueInjector!int, MyIntInjector);
|
* container.register!(ValueInjector!int, MyIntInjector);
|
||||||
* ---
|
* ---
|
||||||
*/
|
*/
|
||||||
interface ValueInjector(Type)
|
interface ValueInjector(Type) {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Get a value from the injector by key.
|
* Get a value from the injector by key.
|
||||||
*
|
*
|
||||||
|
|
|
@ -10,12 +10,10 @@ import poodinis.test.testclasses;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
// Test autowiring concrete type to existing instance
|
// Test autowiring concrete type to existing instance
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
auto componentB = new ComponentB();
|
auto componentB = new ComponentB();
|
||||||
|
@ -24,8 +22,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring interface type to existing instance
|
// Test autowiring interface type to existing instance
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
|
@ -34,8 +31,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring private members
|
// Test autowiring private members
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
|
@ -45,8 +41,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring will only happen once
|
// Test autowiring will only happen once
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC).newInstance();
|
container.register!(InterfaceA, ComponentC).newInstance();
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
|
@ -59,8 +54,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring unregistered type
|
// Test autowiring unregistered type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto componentD = new ComponentD();
|
auto componentD = new ComponentD();
|
||||||
assertThrown!(ResolveException)(container.autowire(componentD),
|
assertThrown!(ResolveException)(container.autowire(componentD),
|
||||||
|
@ -68,8 +62,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring member with non-autowire attribute does not autowire
|
// Test autowiring member with non-autowire attribute does not autowire
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto componentE = new ComponentE();
|
auto componentE = new ComponentE();
|
||||||
container.autowire(componentE);
|
container.autowire(componentE);
|
||||||
|
@ -78,8 +71,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire class with alias declaration
|
// Test autowire class with alias declaration
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
|
auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
|
||||||
|
@ -91,8 +83,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire class with qualifier
|
// Test autowire class with qualifier
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
|
@ -105,8 +96,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire class with multiple qualifiers
|
// Test autowire class with multiple qualifiers
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
|
@ -123,8 +113,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test getting instance from autowired registration will autowire instance
|
// Test getting instance from autowired registration will autowire instance
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
|
|
||||||
|
@ -137,8 +126,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring a dynamic array with all qualified types
|
// Test autowiring a dynamic array with all qualified types
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(InterfaceA, ComponentC);
|
container.register!(InterfaceA, ComponentC);
|
||||||
container.register!(InterfaceA, ComponentX);
|
container.register!(InterfaceA, ComponentX);
|
||||||
|
@ -150,8 +138,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring new instance of singleinstance registration with newInstance UDA
|
// Test autowiring new instance of singleinstance registration with newInstance UDA
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
|
|
||||||
|
@ -165,8 +152,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring members from base class
|
// Test autowiring members from base class
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentA;
|
container.register!ComponentA;
|
||||||
container.register!ComponentB;
|
container.register!ComponentB;
|
||||||
|
@ -179,8 +165,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring optional dependencies
|
// Test autowiring optional dependencies
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto instance = new OuttaTime();
|
auto instance = new OuttaTime();
|
||||||
|
|
||||||
|
@ -192,8 +177,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring class using value injection
|
// Test autowiring class using value injection
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
container.register!(ValueInjector!int, TestInjector);
|
container.register!(ValueInjector!int, TestInjector);
|
||||||
|
@ -207,8 +191,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring classes with recursive template parameters
|
// Test autowiring classes with recursive template parameters
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!CircularTemplateComponentA;
|
container.register!CircularTemplateComponentA;
|
||||||
container.register!CircularTemplateComponentB;
|
container.register!CircularTemplateComponentB;
|
||||||
|
@ -224,8 +207,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring class where a method is marked with @Autowire does nothing
|
// Test autowiring class where a method is marked with @Autowire does nothing
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
// It should also not show deprecation warning:
|
// It should also not show deprecation warning:
|
||||||
// Deprecation: `__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `lala`
|
// 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
|
// the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from
|
||||||
|
|
|
@ -12,21 +12,18 @@ import poodinis.test.foreigndependencies;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
import core.thread;
|
import core.thread;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
// Test register concrete type
|
// Test register concrete type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto registration = container.register!TestClass;
|
auto registration = container.register!TestClass;
|
||||||
assert(registration.registeredType == typeid(TestClass),
|
assert(registration.registeredType == typeid(TestClass),
|
||||||
"Type of registered type not the same");
|
"Type of registered type not the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve registered type
|
// Test resolve registered type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass;
|
container.register!TestClass;
|
||||||
TestClass actualInstance = container.resolve!TestClass;
|
TestClass actualInstance = container.resolve!TestClass;
|
||||||
|
@ -35,81 +32,73 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test register interface
|
// Test register interface
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(TestInterface, TestClass);
|
container.register!(TestInterface, TestClass);
|
||||||
TestInterface actualInstance = container.resolve!TestInterface;
|
TestInterface actualInstance = container.resolve!TestInterface;
|
||||||
assert(actualInstance !is null, "Resolved type is null");
|
assert(actualInstance !is null, "Resolved type is null");
|
||||||
assert(cast(TestInterface) actualInstance,
|
assert(cast(TestInterface) actualInstance,
|
||||||
"Resolved class is not the same type as expected");
|
"Resolved class is not the same type as expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve non-registered type
|
// Test resolve non-registered type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
assertThrown!ResolveException(container.resolve!TestClass,
|
assertThrown!ResolveException(container.resolve!TestClass,
|
||||||
"Resolving non-registered type does not fail");
|
"Resolving non-registered type does not fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test clear registrations
|
// Test clear registrations
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass;
|
container.register!TestClass;
|
||||||
container.clearAllRegistrations();
|
container.clearAllRegistrations();
|
||||||
assertThrown!ResolveException(container.resolve!TestClass,
|
assertThrown!ResolveException(container.resolve!TestClass,
|
||||||
"Resolving cleared type does not fail");
|
"Resolving cleared type does not fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve single instance for type
|
// Test resolve single instance for type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass.singleInstance();
|
container.register!TestClass.singleInstance();
|
||||||
auto instance1 = container.resolve!TestClass;
|
auto instance1 = container.resolve!TestClass;
|
||||||
auto instance2 = container.resolve!TestClass;
|
auto instance2 = container.resolve!TestClass;
|
||||||
assert(instance1 is instance2,
|
assert(instance1 is instance2,
|
||||||
"Resolved instance from single instance scope is not the each time it is resolved");
|
"Resolved instance from single instance scope is not the each time it is resolved");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve new instance for type
|
// Test resolve new instance for type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass.newInstance();
|
container.register!TestClass.newInstance();
|
||||||
auto instance1 = container.resolve!TestClass;
|
auto instance1 = container.resolve!TestClass;
|
||||||
auto instance2 = container.resolve!TestClass;
|
auto instance2 = container.resolve!TestClass;
|
||||||
assert(instance1 !is instance2,
|
assert(instance1 !is instance2,
|
||||||
"Resolved instance from new instance scope is the same each time it is resolved");
|
"Resolved instance from new instance scope is the same each time it is resolved");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve existing instance for type
|
// Test resolve existing instance for type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto expectedInstance = new TestClass();
|
auto expectedInstance = new TestClass();
|
||||||
container.register!TestClass.existingInstance(expectedInstance);
|
container.register!TestClass.existingInstance(expectedInstance);
|
||||||
auto actualInstance = container.resolve!TestClass;
|
auto actualInstance = container.resolve!TestClass;
|
||||||
assert(expectedInstance is actualInstance,
|
assert(expectedInstance is actualInstance,
|
||||||
"Resolved instance from existing instance scope is not the same as the registered instance");
|
"Resolved instance from existing instance scope is not the same as the registered instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating instance via custom initializer on resolve
|
// Test creating instance via custom initializer on resolve
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto expectedInstance = new TestClass();
|
auto expectedInstance = new TestClass();
|
||||||
container.register!TestClass.initializedBy({ return expectedInstance; });
|
container.register!TestClass.initializedBy({ return expectedInstance; });
|
||||||
auto actualInstance = container.resolve!TestClass;
|
auto actualInstance = container.resolve!TestClass;
|
||||||
assert(expectedInstance is actualInstance,
|
assert(expectedInstance is actualInstance,
|
||||||
"Resolved instance does not come from the custom initializer");
|
"Resolved instance does not come from the custom initializer");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating instance via initializedBy creates new instance every time
|
// Test creating instance via initializedBy creates new instance every time
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass.initializedBy({ return new TestClass(); });
|
container.register!TestClass.initializedBy({ return new TestClass(); });
|
||||||
auto firstInstance = container.resolve!TestClass;
|
auto firstInstance = container.resolve!TestClass;
|
||||||
|
@ -118,8 +107,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating instance via initializedOnceBy creates a singleton instance
|
// Test creating instance via initializedOnceBy creates a singleton instance
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass.initializedOnceBy({ return new TestClass(); });
|
container.register!TestClass.initializedOnceBy({ return new TestClass(); });
|
||||||
auto firstInstance = container.resolve!TestClass;
|
auto firstInstance = container.resolve!TestClass;
|
||||||
|
@ -128,32 +116,29 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire resolved instances
|
// Test autowire resolved instances
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!AutowiredClass;
|
container.register!AutowiredClass;
|
||||||
container.register!ComponentClass;
|
container.register!ComponentClass;
|
||||||
auto componentInstance = container.resolve!ComponentClass;
|
auto componentInstance = container.resolve!ComponentClass;
|
||||||
auto autowiredInstance = container.resolve!AutowiredClass;
|
auto autowiredInstance = container.resolve!AutowiredClass;
|
||||||
assert(componentInstance.autowiredClass is autowiredInstance,
|
assert(componentInstance.autowiredClass is autowiredInstance,
|
||||||
"Member is not autowired upon resolving");
|
"Member is not autowired upon resolving");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test circular autowiring
|
// Test circular autowiring
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ComponentMouse;
|
container.register!ComponentMouse;
|
||||||
container.register!ComponentCat;
|
container.register!ComponentCat;
|
||||||
auto mouse = container.resolve!ComponentMouse;
|
auto mouse = container.resolve!ComponentMouse;
|
||||||
auto cat = container.resolve!ComponentCat;
|
auto cat = container.resolve!ComponentCat;
|
||||||
assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat,
|
assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat,
|
||||||
"Circular dependencies should be autowirable");
|
"Circular dependencies should be autowirable");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test remove registration
|
// Test remove registration
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass;
|
container.register!TestClass;
|
||||||
container.removeRegistration!TestClass;
|
container.removeRegistration!TestClass;
|
||||||
|
@ -161,8 +146,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring does not autowire member where instance is non-null
|
// Test autowiring does not autowire member where instance is non-null
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto existingA = new AutowiredClass();
|
auto existingA = new AutowiredClass();
|
||||||
auto existingB = new ComponentClass();
|
auto existingB = new ComponentClass();
|
||||||
|
@ -174,12 +158,11 @@ version (unittest)
|
||||||
auto resolvedB = container.resolve!ComponentClass;
|
auto resolvedB = container.resolve!ComponentClass;
|
||||||
|
|
||||||
assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA,
|
assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA,
|
||||||
"Autowiring shouldn't rewire member when it is already wired to an instance");
|
"Autowiring shouldn't rewire member when it is already wired to an instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring circular dependency by third-degree
|
// Test autowiring circular dependency by third-degree
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Eenie;
|
container.register!Eenie;
|
||||||
container.register!Meenie;
|
container.register!Meenie;
|
||||||
|
@ -188,12 +171,11 @@ version (unittest)
|
||||||
auto eenie = container.resolve!Eenie;
|
auto eenie = container.resolve!Eenie;
|
||||||
|
|
||||||
assert(eenie.meenie.moe.eenie is eenie,
|
assert(eenie.meenie.moe.eenie is eenie,
|
||||||
"Autowiring third-degree circular dependency failed");
|
"Autowiring third-degree circular dependency failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring deep circular dependencies
|
// Test autowiring deep circular dependencies
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Ittie;
|
container.register!Ittie;
|
||||||
container.register!Bittie;
|
container.register!Bittie;
|
||||||
|
@ -205,8 +187,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time
|
// Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Ittie.newInstance();
|
container.register!Ittie.newInstance();
|
||||||
container.register!Bittie.newInstance();
|
container.register!Bittie.newInstance();
|
||||||
|
@ -215,12 +196,11 @@ version (unittest)
|
||||||
auto ittie = container.resolve!Ittie;
|
auto ittie = container.resolve!Ittie;
|
||||||
|
|
||||||
assert(ittie.bittie.banana.bittie.banana is null,
|
assert(ittie.bittie.banana.bittie.banana is null,
|
||||||
"Autowiring deep dependencies with newInstance scope autowired a reoccuring type.");
|
"Autowiring deep dependencies with newInstance scope autowired a reoccuring type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring type registered by interface
|
// Test autowiring type registered by interface
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Bunena;
|
container.register!Bunena;
|
||||||
container.register!Bittie;
|
container.register!Bittie;
|
||||||
|
@ -230,21 +210,17 @@ version (unittest)
|
||||||
.resolve!SuperInterface;
|
.resolve!SuperInterface;
|
||||||
|
|
||||||
assert(!(superInstance.banana is null),
|
assert(!(superInstance.banana is null),
|
||||||
"Instance which was resolved by interface type was not autowired.");
|
"Instance which was resolved by interface type was not autowired.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test reusing a container after clearing all registrations
|
// Test reusing a container after clearing all registrations
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Banana;
|
container.register!Banana;
|
||||||
container.clearAllRegistrations();
|
container.clearAllRegistrations();
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
container.resolve!Banana;
|
container.resolve!Banana;
|
||||||
}
|
} catch (ResolveException e) {
|
||||||
catch (ResolveException e)
|
|
||||||
{
|
|
||||||
container.register!Banana;
|
container.register!Banana;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -252,16 +228,14 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test register multiple concrete classess to same interface type
|
// Test register multiple concrete classess to same interface type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
container.register!(Color, Red);
|
container.register!(Color, Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test removing all registrations for type with multiple registrations.
|
// Test removing all registrations for type with multiple registrations.
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
container.register!(Color, Red);
|
container.register!(Color, Red);
|
||||||
|
@ -269,36 +243,30 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering same registration again
|
// Test registering same registration again
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto firstRegistration = container.register!(Color, Blue);
|
auto firstRegistration = container.register!(Color, Blue);
|
||||||
auto secondRegistration = container.register!(Color, Blue);
|
auto secondRegistration = container.register!(Color, Blue);
|
||||||
|
|
||||||
assert(firstRegistration is secondRegistration,
|
assert(firstRegistration is secondRegistration,
|
||||||
"First registration is not the same as the second of equal types");
|
"First registration is not the same as the second of equal types");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve registration with multiple qualifiers
|
// Test resolve registration with multiple qualifiers
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
container.register!(Color, Red);
|
container.register!(Color, Red);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
container.resolve!Color;
|
container.resolve!Color;
|
||||||
}
|
} catch (ResolveException e) {
|
||||||
catch (ResolveException e)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolve registration with multiple qualifiers using a qualifier
|
// Test resolve registration with multiple qualifiers using a qualifier
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
container.register!(Color, Red);
|
container.register!(Color, Red);
|
||||||
|
@ -306,14 +274,13 @@ version (unittest)
|
||||||
auto redInstance = container.resolve!(Color, Red);
|
auto redInstance = container.resolve!(Color, Red);
|
||||||
|
|
||||||
assert(blueInstance !is redInstance,
|
assert(blueInstance !is redInstance,
|
||||||
"Resolving type with multiple, different registrations yielded the same instance");
|
"Resolving type with multiple, different registrations yielded the same instance");
|
||||||
assert(blueInstance !is null, "Resolved blue instance to null");
|
assert(blueInstance !is null, "Resolved blue instance to null");
|
||||||
assert(redInstance !is null, "Resolved red instance to null");
|
assert(redInstance !is null, "Resolved red instance to null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire of unqualified member typed by interface.
|
// Test autowire of unqualified member typed by interface.
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Spiders;
|
container.register!Spiders;
|
||||||
container.register!(TestInterface, TestClass);
|
container.register!(TestInterface, TestClass);
|
||||||
|
@ -324,32 +291,29 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register existing registration
|
// Register existing registration
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto firstRegistration = container.register!TestClass;
|
auto firstRegistration = container.register!TestClass;
|
||||||
auto secondRegistration = container.register!TestClass;
|
auto secondRegistration = container.register!TestClass;
|
||||||
|
|
||||||
assert(firstRegistration is secondRegistration,
|
assert(firstRegistration is secondRegistration,
|
||||||
"Registering the same registration twice registers the dependencies twice.");
|
"Registering the same registration twice registers the dependencies twice.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register existing registration by supertype
|
// Register existing registration by supertype
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto firstRegistration = container.register!(TestInterface, TestClass);
|
auto firstRegistration = container.register!(TestInterface, TestClass);
|
||||||
auto secondRegistration = container.register!(TestInterface, TestClass);
|
auto secondRegistration = container.register!(TestInterface, TestClass);
|
||||||
|
|
||||||
assert(firstRegistration is secondRegistration,
|
assert(firstRegistration is secondRegistration,
|
||||||
"Registering the same registration by super type twice registers the dependencies twice.");
|
"Registering the same registration by super type twice registers the dependencies twice.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve dependency depending on itself
|
// Resolve dependency depending on itself
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Recursive;
|
container.register!Recursive;
|
||||||
|
|
||||||
|
@ -357,12 +321,11 @@ version (unittest)
|
||||||
|
|
||||||
assert(instance.recursive is instance, "Resolving dependency that depends on itself fails.");
|
assert(instance.recursive is instance, "Resolving dependency that depends on itself fails.");
|
||||||
assert(instance.recursive.recursive is instance,
|
assert(instance.recursive.recursive is instance,
|
||||||
"Resolving dependency that depends on itself fails.");
|
"Resolving dependency that depends on itself fails.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowire stack pop-back
|
// Test autowire stack pop-back
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Moolah;
|
container.register!Moolah;
|
||||||
container.register!Wants.newInstance();
|
container.register!Wants.newInstance();
|
||||||
|
@ -375,8 +338,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving registration registered in different thread
|
// Test resolving registration registered in different thread
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto thread = new Thread(delegate() { container.register!TestClass; });
|
auto thread = new Thread(delegate() { container.register!TestClass; });
|
||||||
|
@ -387,8 +349,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving instance previously resolved in different thread
|
// Test resolving instance previously resolved in different thread
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
shared(TestClass) actualTestClass;
|
shared(TestClass) actualTestClass;
|
||||||
|
|
||||||
|
@ -403,31 +364,28 @@ version (unittest)
|
||||||
shared(TestClass) expectedTestClass = cast(shared(TestClass)) container.resolve!TestClass;
|
shared(TestClass) expectedTestClass = cast(shared(TestClass)) container.resolve!TestClass;
|
||||||
|
|
||||||
assert(expectedTestClass is actualTestClass,
|
assert(expectedTestClass is actualTestClass,
|
||||||
"Instance resolved in main thread is not the one resolved in thread");
|
"Instance resolved in main thread is not the one resolved in thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering type with option doNotAddConcreteTypeRegistration
|
// Test registering type with option doNotAddConcreteTypeRegistration
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(TestInterface,
|
container.register!(TestInterface,
|
||||||
TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration);
|
TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration);
|
||||||
|
|
||||||
auto firstInstance = container.resolve!TestInterface;
|
auto firstInstance = container.resolve!TestInterface;
|
||||||
assertThrown!ResolveException(container.resolve!TestClass);
|
assertThrown!ResolveException(container.resolve!TestClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing
|
// Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration);
|
container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration);
|
||||||
container.resolve!TestClass;
|
container.resolve!TestClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering type will register by contrete type by default
|
// Test registering type will register by contrete type by default
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(TestInterface, TestClass);
|
container.register!(TestInterface, TestClass);
|
||||||
|
|
||||||
|
@ -438,8 +396,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving all registrations to an interface
|
// Test resolving all registrations to an interface
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
container.register!(Color, Red);
|
container.register!(Color, Red);
|
||||||
|
@ -450,8 +407,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring instances resolved in array
|
// Test autowiring instances resolved in array
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!UnrelatedClass;
|
container.register!UnrelatedClass;
|
||||||
container.register!(TestInterface, TestClassDeux);
|
container.register!(TestInterface, TestClassDeux);
|
||||||
|
@ -463,45 +419,40 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set persistent registration options
|
// Test set persistent registration options
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.setPersistentRegistrationOptions(
|
container.setPersistentRegistrationOptions(
|
||||||
RegistrationOption.doNotAddConcreteTypeRegistration);
|
RegistrationOption.doNotAddConcreteTypeRegistration);
|
||||||
container.register!(TestInterface, TestClass);
|
container.register!(TestInterface, TestClass);
|
||||||
assertThrown!ResolveException(container.resolve!TestClass);
|
assertThrown!ResolveException(container.resolve!TestClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test unset persistent registration options
|
// Test unset persistent registration options
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.setPersistentRegistrationOptions(
|
container.setPersistentRegistrationOptions(
|
||||||
RegistrationOption.doNotAddConcreteTypeRegistration);
|
RegistrationOption.doNotAddConcreteTypeRegistration);
|
||||||
container.unsetPersistentRegistrationOptions();
|
container.unsetPersistentRegistrationOptions();
|
||||||
container.register!(TestInterface, TestClass);
|
container.register!(TestInterface, TestClass);
|
||||||
container.resolve!TestClass;
|
container.resolve!TestClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registration when resolving
|
// Test registration when resolving
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving);
|
container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving);
|
||||||
container.resolve!TestClass;
|
container.resolve!TestClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set persistent resolve options
|
// Test set persistent resolve options
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
|
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
|
||||||
container.resolve!TestClass;
|
container.resolve!TestClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test unset persistent resolve options
|
// Test unset persistent resolve options
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
|
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
|
||||||
container.unsetPersistentResolveOptions();
|
container.unsetPersistentResolveOptions();
|
||||||
|
@ -509,32 +460,28 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test ResolveOption registerBeforeResolving fails for interfaces
|
// Test ResolveOption registerBeforeResolving fails for interfaces
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
assertThrown!ResolveException(
|
assertThrown!ResolveException(
|
||||||
container.resolve!TestInterface(ResolveOption.registerBeforeResolving));
|
container.resolve!TestInterface(ResolveOption.registerBeforeResolving));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test ResolveOption noResolveException does not throw
|
// Test ResolveOption noResolveException does not throw
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto instance = container.resolve!TestInterface(ResolveOption.noResolveException);
|
auto instance = container.resolve!TestInterface(ResolveOption.noResolveException);
|
||||||
assert(instance is null);
|
assert(instance is null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveOption noResolveException does not throw for resolveAll
|
// ResolveOption noResolveException does not throw for resolveAll
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException);
|
auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException);
|
||||||
assert(instances.length == 0);
|
assert(instances.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowired, constructor injected class
|
// Test autowired, constructor injected class
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Red;
|
container.register!Red;
|
||||||
container.register!Moolah;
|
container.register!Moolah;
|
||||||
|
@ -548,8 +495,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowired, constructor injected class where constructor argument is templated
|
// Test autowired, constructor injected class where constructor argument is templated
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!PieChart;
|
container.register!PieChart;
|
||||||
container.register!(TemplatedComponent!PieChart);
|
container.register!(TemplatedComponent!PieChart);
|
||||||
|
@ -562,8 +508,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor with super-type parameter
|
// Test injecting constructor with super-type parameter
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Wallpaper;
|
container.register!Wallpaper;
|
||||||
container.register!(Color, Blue);
|
container.register!(Color, Blue);
|
||||||
|
@ -574,8 +519,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test prevention of circular dependencies during constructor injection
|
// Test prevention of circular dependencies during constructor injection
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Pot;
|
container.register!Pot;
|
||||||
container.register!Kettle;
|
container.register!Kettle;
|
||||||
|
@ -584,8 +528,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test prevention of transitive circular dependencies during constructor injection
|
// Test prevention of transitive circular dependencies during constructor injection
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Rock;
|
container.register!Rock;
|
||||||
container.register!Paper;
|
container.register!Paper;
|
||||||
|
@ -595,8 +538,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of foreign dependency in constructor
|
// Test injection of foreign dependency in constructor
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Ola;
|
container.register!Ola;
|
||||||
container.register!Hello;
|
container.register!Hello;
|
||||||
|
@ -604,8 +546,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PostConstruct method is called after resolving a dependency
|
// Test PostConstruct method is called after resolving a dependency
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!PostConstructionDependency;
|
container.register!PostConstructionDependency;
|
||||||
|
|
||||||
|
@ -614,8 +555,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PostConstruct of base type is called
|
// Test PostConstruct of base type is called
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ChildOfPostConstruction;
|
container.register!ChildOfPostConstruction;
|
||||||
|
|
||||||
|
@ -624,8 +564,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PostConstruct of class implementing interface is not called
|
// Test PostConstruct of class implementing interface is not called
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ButThereWontBe;
|
container.register!ButThereWontBe;
|
||||||
|
|
||||||
|
@ -634,8 +573,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test postconstruction happens after autowiring and value injection
|
// Test postconstruction happens after autowiring and value injection
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!int, PostConstructingIntInjector);
|
container.register!(ValueInjector!int, PostConstructingIntInjector);
|
||||||
container.register!PostConstructionDependency;
|
container.register!PostConstructionDependency;
|
||||||
|
@ -644,8 +582,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PreDestroy is called when removing a registration
|
// Test PreDestroy is called when removing a registration
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!PreDestroyerOfFates;
|
container.register!PreDestroyerOfFates;
|
||||||
auto instance = container.resolve!PreDestroyerOfFates;
|
auto instance = container.resolve!PreDestroyerOfFates;
|
||||||
|
@ -654,8 +591,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PreDestroy is called when removing all registrations
|
// Test PreDestroy is called when removing all registrations
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!PreDestroyerOfFates;
|
container.register!PreDestroyerOfFates;
|
||||||
auto instance = container.resolve!PreDestroyerOfFates;
|
auto instance = container.resolve!PreDestroyerOfFates;
|
||||||
|
@ -664,8 +600,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PreDestroy is called when the container is destroyed
|
// Test PreDestroy is called when the container is destroyed
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!PreDestroyerOfFates;
|
container.register!PreDestroyerOfFates;
|
||||||
auto instance = container.resolve!PreDestroyerOfFates;
|
auto instance = container.resolve!PreDestroyerOfFates;
|
||||||
|
@ -675,8 +610,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test register class by ancestor type
|
// Test register class by ancestor type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(Grandma, Kid);
|
container.register!(Grandma, Kid);
|
||||||
auto instance = container.resolve!Grandma;
|
auto instance = container.resolve!Grandma;
|
||||||
|
|
|
@ -10,12 +10,10 @@ import poodinis.test.testclasses;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
//Test register component registrations from context
|
//Test register component registrations from context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -25,8 +23,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test non-annotated methods are not registered
|
//Test non-annotated methods are not registered
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -34,8 +31,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register component by base type
|
//Test register component by base type
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -44,8 +40,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register components with multiple candidates
|
//Test register components with multiple candidates
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -58,8 +53,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test register component as prototype
|
//Test register component as prototype
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto context = new TestContext();
|
auto context = new TestContext();
|
||||||
context.registerContextComponents(container);
|
context.registerContextComponents(container);
|
||||||
|
@ -72,8 +66,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test setting up simple dependencies through application context
|
// Test setting up simple dependencies through application context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!SimpleContext;
|
container.registerContext!SimpleContext;
|
||||||
auto instance = container.resolve!CakeChart;
|
auto instance = container.resolve!CakeChart;
|
||||||
|
@ -82,8 +75,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving dependency from registered application context
|
// Test resolving dependency from registered application context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!SimpleContext;
|
container.registerContext!SimpleContext;
|
||||||
auto instance = container.resolve!Apple;
|
auto instance = container.resolve!Apple;
|
||||||
|
@ -92,8 +84,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring application context
|
// Test autowiring application context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!Apple;
|
container.register!Apple;
|
||||||
container.registerContext!AutowiredTestContext;
|
container.registerContext!AutowiredTestContext;
|
||||||
|
@ -104,8 +95,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test autowiring application context with dependencies registered in same context
|
// Test autowiring application context with dependencies registered in same context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!ComplexAutowiredTestContext;
|
container.registerContext!ComplexAutowiredTestContext;
|
||||||
auto instance = container.resolve!ClassWrapperWrapper;
|
auto instance = container.resolve!ClassWrapperWrapper;
|
||||||
|
@ -118,8 +108,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving registered context
|
// Test resolving registered context
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.registerContext!TestContext;
|
container.registerContext!TestContext;
|
||||||
container.resolve!ApplicationContext;
|
container.resolve!ApplicationContext;
|
||||||
|
|
|
@ -10,15 +10,13 @@ import poodinis.test.testclasses;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
// Test instance factory with singletons
|
// Test instance factory with singletons
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
||||||
CreatesSingleton.yes);
|
CreatesSingleton.yes);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
|
@ -27,11 +25,10 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test instance factory with new instances
|
// Test instance factory with new instances
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
||||||
CreatesSingleton.no);
|
CreatesSingleton.no);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
|
@ -40,39 +37,35 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test instance factory with existing instances
|
// Test instance factory with existing instances
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto existingInstance = new TestImplementation();
|
auto existingInstance = new TestImplementation();
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
||||||
CreatesSingleton.yes, existingInstance);
|
CreatesSingleton.yes, existingInstance);
|
||||||
auto instanceOne = factory.getInstance();
|
auto instanceOne = factory.getInstance();
|
||||||
auto instanceTwo = factory.getInstance();
|
auto instanceTwo = factory.getInstance();
|
||||||
|
|
||||||
assert(instanceOne is existingInstance,
|
assert(instanceOne is existingInstance,
|
||||||
"Created factory instance is not the existing instance");
|
"Created factory instance is not the existing instance");
|
||||||
assert(instanceTwo is existingInstance,
|
assert(instanceTwo is existingInstance,
|
||||||
"Created factory instance is not the existing instance when called again");
|
"Created factory instance is not the existing instance when called again");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test instance factory with existing instances when setting singleton flag to "no"
|
// Test instance factory with existing instances when setting singleton flag to "no"
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto existingInstance = new TestImplementation();
|
auto existingInstance = new TestImplementation();
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation),
|
||||||
CreatesSingleton.no, existingInstance);
|
CreatesSingleton.no, existingInstance);
|
||||||
auto instance = factory.getInstance();
|
auto instance = factory.getInstance();
|
||||||
|
|
||||||
assert(instance is existingInstance,
|
assert(instance is existingInstance,
|
||||||
"Created factory instance is not the existing instance");
|
"Created factory instance is not the existing instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating instance using custom factory method
|
// Test creating instance using custom factory method
|
||||||
unittest
|
unittest {
|
||||||
{
|
Object factoryMethod() {
|
||||||
Object factoryMethod()
|
|
||||||
{
|
|
||||||
auto instance = new TestImplementation();
|
auto instance = new TestImplementation();
|
||||||
instance.someContent = "Ducks!";
|
instance.someContent = "Ducks!";
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -80,17 +73,16 @@ version (unittest)
|
||||||
|
|
||||||
auto factory = new InstanceFactory();
|
auto factory = new InstanceFactory();
|
||||||
factory.factoryParameters = InstanceFactoryParameters(null,
|
factory.factoryParameters = InstanceFactoryParameters(null,
|
||||||
CreatesSingleton.yes, null, &factoryMethod);
|
CreatesSingleton.yes, null, &factoryMethod);
|
||||||
auto instance = cast(TestImplementation) factory.getInstance();
|
auto instance = cast(TestImplementation) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null,
|
assert(instance !is null,
|
||||||
"No instance was created by factory or could not be cast to expected type");
|
"No instance was created by factory or could not be cast to expected type");
|
||||||
assert(instance.someContent == "Ducks!");
|
assert(instance.someContent == "Ducks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class
|
// Test injecting constructor of class
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
|
@ -102,14 +94,13 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with multiple constructors injects the first candidate
|
// Test injecting constructor of class with multiple constructors injects the first candidate
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(
|
||||||
container);
|
container);
|
||||||
auto instance = cast(ClassWithMultipleConstructors) factory.getInstance();
|
auto instance = cast(ClassWithMultipleConstructors) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
|
@ -118,14 +109,13 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with multiple constructor parameters
|
// Test injecting constructor of class with multiple constructor parameters
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
container.register!TestImplementation;
|
container.register!TestImplementation;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(
|
||||||
container);
|
container);
|
||||||
auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance();
|
auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
|
@ -134,13 +124,12 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with primitive constructor parameters
|
// Test injecting constructor of class with primitive constructor parameters
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(
|
||||||
container);
|
container);
|
||||||
auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance();
|
auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance();
|
||||||
|
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
|
@ -148,8 +137,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with struct constructor parameters
|
// Test injecting constructor of class with struct constructor parameters
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!SomeOtherClassThen;
|
container.register!SomeOtherClassThen;
|
||||||
|
|
||||||
|
@ -161,8 +149,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with empty constructor will skip injection
|
// Test injecting constructor of class with empty constructor will skip injection
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container);
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container);
|
||||||
|
@ -173,12 +160,11 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting constructor of class with no candidates fails
|
// Test injecting constructor of class with no candidates fails
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
||||||
auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(
|
auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(
|
||||||
container);
|
container);
|
||||||
|
|
||||||
assertThrown!InstanceCreationException(factory.getInstance());
|
assertThrown!InstanceCreationException(factory.getInstance());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
|
|
||||||
module poodinis.test.foreigndependencies;
|
module poodinis.test.foreigndependencies;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
class Ola {
|
||||||
class Ola
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,65 +10,59 @@ import poodinis.test.testclasses;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
// Test getting instance without scope defined throws exception
|
// Test getting instance without scope defined throws exception
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(typeid(TestType), null, null, null);
|
Registration registration = new Registration(typeid(TestType), null, null, null);
|
||||||
assertThrown!(InstanceCreationException)(registration.getInstance(), null);
|
assertThrown!(InstanceCreationException)(registration.getInstance(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set single instance scope using scope setter
|
// Test set single instance scope using scope setter
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(null, typeid(TestType),
|
Registration registration = new Registration(null, typeid(TestType),
|
||||||
new InstanceFactory(), null).initializeFactoryType();
|
new InstanceFactory(), null).initializeFactoryType();
|
||||||
auto chainedRegistration = registration.singleInstance();
|
auto chainedRegistration = registration.singleInstance();
|
||||||
auto instance1 = registration.getInstance();
|
auto instance1 = registration.getInstance();
|
||||||
auto instance2 = registration.getInstance();
|
auto instance2 = registration.getInstance();
|
||||||
assert(instance1 is instance2,
|
assert(instance1 is instance2,
|
||||||
"Registration with single instance scope did not return the same instance");
|
"Registration with single instance scope did not return the same instance");
|
||||||
assert(registration is chainedRegistration,
|
assert(registration is chainedRegistration,
|
||||||
"Registration returned by scope setting is not the same as the registration being set");
|
"Registration returned by scope setting is not the same as the registration being set");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set new instance scope using scope setter
|
// Test set new instance scope using scope setter
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(null, typeid(TestType),
|
Registration registration = new Registration(null, typeid(TestType),
|
||||||
new InstanceFactory(), null).initializeFactoryType();
|
new InstanceFactory(), null).initializeFactoryType();
|
||||||
auto chainedRegistration = registration.newInstance();
|
auto chainedRegistration = registration.newInstance();
|
||||||
auto instance1 = registration.getInstance();
|
auto instance1 = registration.getInstance();
|
||||||
auto instance2 = registration.getInstance();
|
auto instance2 = registration.getInstance();
|
||||||
assert(instance1 !is instance2,
|
assert(instance1 !is instance2,
|
||||||
"Registration with new instance scope did not return a different instance");
|
"Registration with new instance scope did not return a different instance");
|
||||||
assert(registration is chainedRegistration,
|
assert(registration is chainedRegistration,
|
||||||
"Registration returned by scope setting is not the same as the registration being set");
|
"Registration returned by scope setting is not the same as the registration being set");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set existing instance scope using scope setter
|
// Test set existing instance scope using scope setter
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(null, null, new InstanceFactory(), null);
|
Registration registration = new Registration(null, null, new InstanceFactory(), null);
|
||||||
auto expectedInstance = new TestType();
|
auto expectedInstance = new TestType();
|
||||||
auto chainedRegistration = registration.existingInstance(expectedInstance);
|
auto chainedRegistration = registration.existingInstance(expectedInstance);
|
||||||
auto actualInstance = registration.getInstance();
|
auto actualInstance = registration.getInstance();
|
||||||
assert(expectedInstance is actualInstance,
|
assert(expectedInstance is actualInstance,
|
||||||
"Registration with existing instance scope did not return the same instance");
|
"Registration with existing instance scope did not return the same instance");
|
||||||
assert(registration is chainedRegistration,
|
assert(registration is chainedRegistration,
|
||||||
"Registration returned by scope setting is not the same as the registration being set");
|
"Registration returned by scope setting is not the same as the registration being set");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test linking registrations
|
// Test linking registrations
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration firstRegistration = new Registration(typeid(TestInterface),
|
Registration firstRegistration = new Registration(typeid(TestInterface),
|
||||||
typeid(TestImplementation), new InstanceFactory(), null).initializeFactoryType()
|
typeid(TestImplementation), new InstanceFactory(), null).initializeFactoryType()
|
||||||
.singleInstance();
|
.singleInstance();
|
||||||
Registration secondRegistration = new Registration(typeid(TestImplementation),
|
Registration secondRegistration = new Registration(typeid(TestImplementation),
|
||||||
typeid(TestImplementation), new InstanceFactory(), null).initializeFactoryType()
|
typeid(TestImplementation), new InstanceFactory(), null).initializeFactoryType()
|
||||||
.singleInstance().linkTo(firstRegistration);
|
.singleInstance().linkTo(firstRegistration);
|
||||||
|
|
||||||
auto firstInstance = firstRegistration.getInstance();
|
auto firstInstance = firstRegistration.getInstance();
|
||||||
|
@ -78,10 +72,9 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test custom factory method via initializedBy
|
// Test custom factory method via initializedBy
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(typeid(TestInterface),
|
Registration registration = new Registration(typeid(TestInterface),
|
||||||
typeid(TestImplementation), new InstanceFactory(), null);
|
typeid(TestImplementation), new InstanceFactory(), null);
|
||||||
|
|
||||||
registration.initializedBy({
|
registration.initializedBy({
|
||||||
auto instance = new TestImplementation();
|
auto instance = new TestImplementation();
|
||||||
|
@ -97,10 +90,9 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test custom factory method via initializedOnceBy
|
// Test custom factory method via initializedOnceBy
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(typeid(TestInterface),
|
Registration registration = new Registration(typeid(TestInterface),
|
||||||
typeid(TestImplementation), new InstanceFactory(), null);
|
typeid(TestImplementation), new InstanceFactory(), null);
|
||||||
|
|
||||||
registration.initializedOnceBy({
|
registration.initializedOnceBy({
|
||||||
auto instance = new TestImplementation();
|
auto instance = new TestImplementation();
|
||||||
|
@ -116,10 +108,9 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test chaining single/new instance scope to initializedBy will not overwrite the factory method.
|
// Test chaining single/new instance scope to initializedBy will not overwrite the factory method.
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
Registration registration = new Registration(typeid(TestInterface),
|
Registration registration = new Registration(typeid(TestInterface),
|
||||||
typeid(TestImplementation), new InstanceFactory(), null);
|
typeid(TestImplementation), new InstanceFactory(), null);
|
||||||
|
|
||||||
registration.initializedBy({
|
registration.initializedBy({
|
||||||
auto instance = new TestImplementation();
|
auto instance = new TestImplementation();
|
||||||
|
|
|
@ -10,92 +10,73 @@ module poodinis.test.testclasses;
|
||||||
import poodinis;
|
import poodinis;
|
||||||
import poodinis.test.foreigndependencies;
|
import poodinis.test.foreigndependencies;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
class ComponentA {
|
||||||
class ComponentA
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentB
|
class ComponentB {
|
||||||
{
|
|
||||||
public @Autowire ComponentA componentA;
|
public @Autowire ComponentA componentA;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InterfaceA
|
interface InterfaceA {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentC : InterfaceA
|
class ComponentC : InterfaceA {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentD
|
class ComponentD {
|
||||||
{
|
|
||||||
public @Autowire InterfaceA componentC = null;
|
public @Autowire InterfaceA componentC = null;
|
||||||
private @Autowire InterfaceA _privateComponentC = null;
|
private @Autowire InterfaceA _privateComponentC = null;
|
||||||
|
|
||||||
public InterfaceA privateComponentC()
|
public InterfaceA privateComponentC() {
|
||||||
{
|
|
||||||
return _privateComponentC;
|
return _privateComponentC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyAttribute
|
class DummyAttribute {
|
||||||
{
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ComponentE
|
class ComponentE {
|
||||||
{
|
|
||||||
@DummyAttribute public ComponentC componentC;
|
@DummyAttribute public ComponentC componentC;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentDeclarationCocktail
|
class ComponentDeclarationCocktail {
|
||||||
{
|
|
||||||
alias noomer = int;
|
alias noomer = int;
|
||||||
|
|
||||||
@Autowire public ComponentA componentA;
|
@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;
|
@Autowire!ComponentX public InterfaceA component;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BootstrapBootstrap
|
class BootstrapBootstrap {
|
||||||
{
|
|
||||||
@Autowire!ComponentX public InterfaceA componentX;
|
@Autowire!ComponentX public InterfaceA componentX;
|
||||||
|
|
||||||
@Autowire!ComponentC public InterfaceA componentC;
|
@Autowire!ComponentC public InterfaceA componentC;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LordOfTheComponents
|
class LordOfTheComponents {
|
||||||
{
|
|
||||||
@Autowire public InterfaceA[] components;
|
@Autowire public InterfaceA[] components;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentCharlie
|
class ComponentCharlie {
|
||||||
{
|
|
||||||
@Autowire @AssignNewInstance public ComponentA componentA;
|
@Autowire @AssignNewInstance public ComponentA componentA;
|
||||||
}
|
}
|
||||||
|
|
||||||
class OuttaTime
|
class OuttaTime {
|
||||||
{
|
|
||||||
@Autowire @OptionalDependency public InterfaceA interfaceA;
|
@Autowire @OptionalDependency public InterfaceA interfaceA;
|
||||||
|
|
||||||
@Autowire @OptionalDependency public ComponentA componentA;
|
@Autowire @OptionalDependency public ComponentA componentA;
|
||||||
|
@ -103,537 +84,423 @@ version (unittest)
|
||||||
@Autowire @OptionalDependency public ComponentC[] componentCs;
|
@Autowire @OptionalDependency public ComponentC[] componentCs;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValuedClass
|
class ValuedClass {
|
||||||
{
|
|
||||||
@Value("values.int")
|
@Value("values.int")
|
||||||
public int intValue;
|
public int intValue;
|
||||||
|
|
||||||
@Autowire public ComponentA unrelated;
|
@Autowire public ComponentA unrelated;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestInjector : ValueInjector!int
|
class TestInjector : ValueInjector!int {
|
||||||
{
|
public override int get(string key) {
|
||||||
public override int get(string key)
|
|
||||||
{
|
|
||||||
assert(key == "values.int");
|
assert(key == "values.int");
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestInterface
|
interface TestInterface {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestClass : TestInterface
|
class TestClass : TestInterface {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestClassDeux : TestInterface
|
class TestClassDeux : TestInterface {
|
||||||
{
|
|
||||||
@Autowire public UnrelatedClass unrelated;
|
@Autowire public UnrelatedClass unrelated;
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnrelatedClass
|
class UnrelatedClass {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FailOnCreationClass
|
class FailOnCreationClass {
|
||||||
{
|
this() {
|
||||||
this()
|
|
||||||
{
|
|
||||||
throw new Exception("This class should not be instantiated");
|
throw new Exception("This class should not be instantiated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowiredClass
|
class AutowiredClass {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentClass
|
class ComponentClass {
|
||||||
{
|
|
||||||
@Autowire public AutowiredClass autowiredClass;
|
@Autowire public AutowiredClass autowiredClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentCat
|
class ComponentCat {
|
||||||
{
|
|
||||||
@Autowire public ComponentMouse mouse;
|
@Autowire public ComponentMouse mouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentMouse
|
class ComponentMouse {
|
||||||
{
|
|
||||||
@Autowire public ComponentCat cat;
|
@Autowire public ComponentCat cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Eenie
|
class Eenie {
|
||||||
{
|
|
||||||
@Autowire public Meenie meenie;
|
@Autowire public Meenie meenie;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Meenie
|
class Meenie {
|
||||||
{
|
|
||||||
@Autowire public Moe moe;
|
@Autowire public Moe moe;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Moe
|
class Moe {
|
||||||
{
|
|
||||||
@Autowire public Eenie eenie;
|
@Autowire public Eenie eenie;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ittie
|
class Ittie {
|
||||||
{
|
|
||||||
@Autowire public Bittie bittie;
|
@Autowire public Bittie bittie;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bittie
|
class Bittie {
|
||||||
{
|
|
||||||
@Autowire public Bunena banana;
|
@Autowire public Bunena banana;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bunena
|
class Bunena {
|
||||||
{
|
|
||||||
@Autowire public Bittie bittie;
|
@Autowire public Bittie bittie;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SuperInterface
|
interface SuperInterface {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SuperImplementation : SuperInterface
|
class SuperImplementation : SuperInterface {
|
||||||
{
|
|
||||||
@Autowire public Bunena banana;
|
@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;
|
@Autowire public TestInterface testMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Recursive
|
class Recursive {
|
||||||
{
|
|
||||||
@Autowire public Recursive recursive;
|
@Autowire public Recursive recursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Moolah
|
class Moolah {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Wants
|
class Wants {
|
||||||
{
|
|
||||||
@Autowire public Moolah moolah;
|
@Autowire public Moolah moolah;
|
||||||
}
|
}
|
||||||
|
|
||||||
class John
|
class John {
|
||||||
{
|
|
||||||
@Autowire public Wants wants;
|
@Autowire public Wants wants;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Cocktail
|
class Cocktail {
|
||||||
{
|
|
||||||
@Autowire public Moolah moolah;
|
@Autowire public Moolah moolah;
|
||||||
|
|
||||||
public Red red;
|
public Red red;
|
||||||
|
|
||||||
this(Red red)
|
this(Red red) {
|
||||||
{
|
|
||||||
this.red = red;
|
this.red = red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Wallpaper
|
class Wallpaper {
|
||||||
{
|
|
||||||
public Color color;
|
public Color color;
|
||||||
|
|
||||||
this(Color color)
|
this(Color color) {
|
||||||
{
|
|
||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Pot
|
class Pot {
|
||||||
{
|
this(Kettle kettle) {
|
||||||
this(Kettle kettle)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Kettle
|
class Kettle {
|
||||||
{
|
this(Pot pot) {
|
||||||
this(Pot pot)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Rock
|
class Rock {
|
||||||
{
|
this(Scissors scissors) {
|
||||||
this(Scissors scissors)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Paper
|
class Paper {
|
||||||
{
|
this(Rock rock) {
|
||||||
this(Rock rock)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Scissors
|
class Scissors {
|
||||||
{
|
this(Paper paper) {
|
||||||
this(Paper paper)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Hello
|
class Hello {
|
||||||
{
|
this(Ola ola) {
|
||||||
this(Ola ola)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostConstructionDependency
|
class PostConstructionDependency {
|
||||||
{
|
|
||||||
public bool postConstructWasCalled = false;
|
public bool postConstructWasCalled = false;
|
||||||
|
|
||||||
@PostConstruct public void callMeMaybe()
|
@PostConstruct public void callMeMaybe() {
|
||||||
{
|
|
||||||
postConstructWasCalled = true;
|
postConstructWasCalled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildOfPostConstruction : PostConstructionDependency
|
class ChildOfPostConstruction : PostConstructionDependency {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ThereWillBePostConstruction
|
interface ThereWillBePostConstruction {
|
||||||
{
|
|
||||||
@PostConstruct void constructIt();
|
@PostConstruct void constructIt();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ButThereWontBe : ThereWillBePostConstruction
|
class ButThereWontBe : ThereWillBePostConstruction {
|
||||||
{
|
|
||||||
public bool postConstructWasCalled = false;
|
public bool postConstructWasCalled = false;
|
||||||
|
|
||||||
public override void constructIt()
|
public override void constructIt() {
|
||||||
{
|
|
||||||
postConstructWasCalled = true;
|
postConstructWasCalled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostConstructWithAutowiring
|
class PostConstructWithAutowiring {
|
||||||
{
|
|
||||||
@Autowire private PostConstructionDependency dependency;
|
@Autowire private PostConstructionDependency dependency;
|
||||||
|
|
||||||
@Value("")
|
@Value("")
|
||||||
private int theNumber = 1;
|
private int theNumber = 1;
|
||||||
|
|
||||||
@PostConstruct public void doIt()
|
@PostConstruct public void doIt() {
|
||||||
{
|
|
||||||
assert(theNumber == 8783);
|
assert(theNumber == 8783);
|
||||||
assert(dependency !is null);
|
assert(dependency !is null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreDestroyerOfFates
|
class PreDestroyerOfFates {
|
||||||
{
|
|
||||||
public bool preDestroyWasCalled = false;
|
public bool preDestroyWasCalled = false;
|
||||||
|
|
||||||
@PreDestroy public void callMeMaybe()
|
@PreDestroy public void callMeMaybe() {
|
||||||
{
|
|
||||||
preDestroyWasCalled = true;
|
preDestroyWasCalled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostConstructingIntInjector : ValueInjector!int
|
class PostConstructingIntInjector : ValueInjector!int {
|
||||||
{
|
int get(string key) {
|
||||||
int get(string key)
|
|
||||||
{
|
|
||||||
return 8783;
|
return 8783;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Fruit
|
interface Fruit {
|
||||||
{
|
|
||||||
string getShape();
|
string getShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Animal
|
interface Animal {
|
||||||
{
|
|
||||||
string getYell();
|
string getYell();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Banana
|
class Banana {
|
||||||
{
|
|
||||||
public string color;
|
public string color;
|
||||||
|
|
||||||
this(string color)
|
this(string color) {
|
||||||
{
|
|
||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Apple
|
class Apple {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Pear : Fruit
|
class Pear : Fruit {
|
||||||
{
|
public override string getShape() {
|
||||||
public override string getShape()
|
|
||||||
{
|
|
||||||
return "Pear shaped";
|
return "Pear shaped";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Rabbit : Animal
|
class Rabbit : Animal {
|
||||||
{
|
public override string getYell() {
|
||||||
public override string getYell()
|
|
||||||
{
|
|
||||||
return "Squeeeeeel";
|
return "Squeeeeeel";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Wolf : Animal
|
class Wolf : Animal {
|
||||||
{
|
public override string getYell() {
|
||||||
public override string getYell()
|
|
||||||
{
|
|
||||||
return "Wooooooooooo";
|
return "Wooooooooooo";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PieChart
|
class PieChart {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CakeChart : PieChart
|
class CakeChart : PieChart {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWrapper
|
class ClassWrapper {
|
||||||
{
|
|
||||||
public Object someClass;
|
public Object someClass;
|
||||||
|
|
||||||
this(Object someClass)
|
this(Object someClass) {
|
||||||
{
|
|
||||||
this.someClass = someClass;
|
this.someClass = someClass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWrapperWrapper
|
class ClassWrapperWrapper {
|
||||||
{
|
|
||||||
public ClassWrapper wrapper;
|
public ClassWrapper wrapper;
|
||||||
|
|
||||||
this(ClassWrapper wrapper)
|
this(ClassWrapper wrapper) {
|
||||||
{
|
|
||||||
this.wrapper = wrapper;
|
this.wrapper = wrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleContext : ApplicationContext
|
class SimpleContext : ApplicationContext {
|
||||||
{
|
public override void registerDependencies(shared(DependencyContainer) container) {
|
||||||
public override void registerDependencies(shared(DependencyContainer) container)
|
|
||||||
{
|
|
||||||
container.register!CakeChart;
|
container.register!CakeChart;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component public Apple apple()
|
@Component public Apple apple() {
|
||||||
{
|
|
||||||
return new Apple();
|
return new Apple();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComplexAutowiredTestContext : ApplicationContext
|
class ComplexAutowiredTestContext : ApplicationContext {
|
||||||
{
|
|
||||||
|
|
||||||
@Autowire private Apple apple;
|
@Autowire private Apple apple;
|
||||||
|
|
||||||
@Autowire protected ClassWrapper classWrapper;
|
@Autowire protected ClassWrapper classWrapper;
|
||||||
|
|
||||||
public override void registerDependencies(shared(DependencyContainer) container)
|
public override void registerDependencies(shared(DependencyContainer) container) {
|
||||||
{
|
|
||||||
container.register!Apple;
|
container.register!Apple;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component public ClassWrapper wrapper()
|
@Component public ClassWrapper wrapper() {
|
||||||
{
|
|
||||||
return new ClassWrapper(apple);
|
return new ClassWrapper(apple);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component public ClassWrapperWrapper wrapperWrapper()
|
@Component public ClassWrapperWrapper wrapperWrapper() {
|
||||||
{
|
|
||||||
return new ClassWrapperWrapper(classWrapper);
|
return new ClassWrapperWrapper(classWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutowiredTestContext : ApplicationContext
|
class AutowiredTestContext : ApplicationContext {
|
||||||
{
|
|
||||||
|
|
||||||
@Autowire private Apple apple;
|
@Autowire private Apple apple;
|
||||||
|
|
||||||
@Component public ClassWrapper wrapper()
|
@Component public ClassWrapper wrapper() {
|
||||||
{
|
|
||||||
return new ClassWrapper(apple);
|
return new ClassWrapper(apple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestContext : ApplicationContext
|
class TestContext : ApplicationContext {
|
||||||
{
|
|
||||||
|
|
||||||
@Component public Banana banana()
|
@Component public Banana banana() {
|
||||||
{
|
|
||||||
return new Banana("Yellow");
|
return new Banana("Yellow");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Apple apple()
|
public Apple apple() {
|
||||||
{
|
|
||||||
return new Apple();
|
return new Apple();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component @RegisterByType!Fruit public Pear pear()
|
@Component @RegisterByType!Fruit public Pear pear() {
|
||||||
{
|
|
||||||
return new Pear();
|
return new Pear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component @RegisterByType!Animal public Rabbit rabbit()
|
@Component @RegisterByType!Animal public Rabbit rabbit() {
|
||||||
{
|
|
||||||
return new Rabbit();
|
return new Rabbit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component @RegisterByType!Animal public Wolf wolf()
|
@Component @RegisterByType!Animal public Wolf wolf() {
|
||||||
{
|
|
||||||
return new Wolf();
|
return new Wolf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component @Prototype public PieChart pieChart()
|
@Component @Prototype public PieChart pieChart() {
|
||||||
{
|
|
||||||
return new PieChart();
|
return new PieChart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestImplementation : TestInterface
|
class TestImplementation : TestInterface {
|
||||||
{
|
|
||||||
public string someContent = "";
|
public string someContent = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
class SomeOtherClassThen
|
class SomeOtherClassThen {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithConstructor
|
class ClassWithConstructor {
|
||||||
{
|
|
||||||
public TestImplementation testImplementation;
|
public TestImplementation testImplementation;
|
||||||
|
|
||||||
this(TestImplementation testImplementation)
|
this(TestImplementation testImplementation) {
|
||||||
{
|
|
||||||
this.testImplementation = testImplementation;
|
this.testImplementation = testImplementation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithMultipleConstructors
|
class ClassWithMultipleConstructors {
|
||||||
{
|
|
||||||
public SomeOtherClassThen someOtherClassThen;
|
public SomeOtherClassThen someOtherClassThen;
|
||||||
public TestImplementation testImplementation;
|
public TestImplementation testImplementation;
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen)
|
this(SomeOtherClassThen someOtherClassThen) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation)
|
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
this.testImplementation = testImplementation;
|
this.testImplementation = testImplementation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithConstructorWithMultipleParameters
|
class ClassWithConstructorWithMultipleParameters {
|
||||||
{
|
|
||||||
public SomeOtherClassThen someOtherClassThen;
|
public SomeOtherClassThen someOtherClassThen;
|
||||||
public TestImplementation testImplementation;
|
public TestImplementation testImplementation;
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation)
|
this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
this.testImplementation = testImplementation;
|
this.testImplementation = testImplementation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithPrimitiveConstructor
|
class ClassWithPrimitiveConstructor {
|
||||||
{
|
|
||||||
public SomeOtherClassThen someOtherClassThen;
|
public SomeOtherClassThen someOtherClassThen;
|
||||||
|
|
||||||
this(string willNotBePicked)
|
this(string willNotBePicked) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen)
|
this(SomeOtherClassThen someOtherClassThen) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithEmptyConstructor
|
class ClassWithEmptyConstructor {
|
||||||
{
|
|
||||||
public SomeOtherClassThen someOtherClassThen;
|
public SomeOtherClassThen someOtherClassThen;
|
||||||
|
|
||||||
this()
|
this() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen)
|
this(SomeOtherClassThen someOtherClassThen) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithNonInjectableConstructor
|
class ClassWithNonInjectableConstructor {
|
||||||
{
|
this(string myName) {
|
||||||
this(string myName)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassWithStructConstructor
|
class ClassWithStructConstructor {
|
||||||
{
|
|
||||||
public SomeOtherClassThen someOtherClassThen;
|
public SomeOtherClassThen someOtherClassThen;
|
||||||
|
|
||||||
this(Thing willNotBePicked)
|
this(Thing willNotBePicked) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this(SomeOtherClassThen someOtherClassThen)
|
this(SomeOtherClassThen someOtherClassThen) {
|
||||||
{
|
|
||||||
this.someOtherClassThen = someOtherClassThen;
|
this.someOtherClassThen = someOtherClassThen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestType
|
class TestType {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dependency
|
class Dependency {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Thing
|
struct Thing {
|
||||||
{
|
|
||||||
int x;
|
int x;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyConfig
|
class MyConfig {
|
||||||
{
|
|
||||||
@Value("conf.stuffs")
|
@Value("conf.stuffs")
|
||||||
int stuffs;
|
int stuffs;
|
||||||
|
|
||||||
|
@ -644,105 +511,83 @@ version (unittest)
|
||||||
Thing thing;
|
Thing thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigWithDefaults
|
class ConfigWithDefaults {
|
||||||
{
|
|
||||||
@Value("conf.missing")
|
@Value("conf.missing")
|
||||||
int noms = 9;
|
int noms = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigWithMandatory
|
class ConfigWithMandatory {
|
||||||
{
|
|
||||||
@MandatoryValue("conf.mustbethere")
|
@MandatoryValue("conf.mustbethere")
|
||||||
int nums;
|
int nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntInjector : ValueInjector!int
|
class IntInjector : ValueInjector!int {
|
||||||
{
|
public override int get(string key) {
|
||||||
public override int get(string key)
|
|
||||||
{
|
|
||||||
assert(key == "conf.stuffs");
|
assert(key == "conf.stuffs");
|
||||||
return 364;
|
return 364;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringInjector : ValueInjector!string
|
class StringInjector : ValueInjector!string {
|
||||||
{
|
public override string get(string key) {
|
||||||
public override string get(string key)
|
|
||||||
{
|
|
||||||
assert(key == "conf.name");
|
assert(key == "conf.name");
|
||||||
return "Le Chef";
|
return "Le Chef";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThingInjector : ValueInjector!Thing
|
class ThingInjector : ValueInjector!Thing {
|
||||||
{
|
public override Thing get(string key) {
|
||||||
public override Thing get(string key)
|
|
||||||
{
|
|
||||||
assert(key == "conf.thing");
|
assert(key == "conf.thing");
|
||||||
return Thing(8899);
|
return Thing(8899);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultIntInjector : ValueInjector!int
|
class DefaultIntInjector : ValueInjector!int {
|
||||||
{
|
public override int get(string key) {
|
||||||
public override int get(string key)
|
|
||||||
{
|
|
||||||
throw new ValueNotAvailableException(key);
|
throw new ValueNotAvailableException(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MandatoryAvailableIntInjector : ValueInjector!int
|
class MandatoryAvailableIntInjector : ValueInjector!int {
|
||||||
{
|
public override int get(string key) {
|
||||||
public override int get(string key)
|
|
||||||
{
|
|
||||||
return 7466;
|
return 7466;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MandatoryUnavailableIntInjector : ValueInjector!int
|
class MandatoryUnavailableIntInjector : ValueInjector!int {
|
||||||
{
|
public override int get(string key) {
|
||||||
public override int get(string key)
|
|
||||||
{
|
|
||||||
throw new ValueNotAvailableException(key);
|
throw new ValueNotAvailableException(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DependencyInjectedIntInjector : ValueInjector!int
|
class DependencyInjectedIntInjector : ValueInjector!int {
|
||||||
{
|
|
||||||
@Autowire public Dependency dependency;
|
@Autowire public Dependency dependency;
|
||||||
|
|
||||||
public override int get(string key)
|
public override int get(string key) {
|
||||||
{
|
|
||||||
return 2345;
|
return 2345;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CircularIntInjector : ValueInjector!int
|
class CircularIntInjector : ValueInjector!int {
|
||||||
{
|
|
||||||
@Autowire public ValueInjector!int dependency;
|
@Autowire public ValueInjector!int dependency;
|
||||||
|
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
|
|
||||||
public override int get(string key)
|
public override int get(string key) {
|
||||||
{
|
|
||||||
count += 1;
|
count += 1;
|
||||||
if (count >= 3)
|
if (count >= 3) {
|
||||||
{
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
return dependency.get(key);
|
return dependency.get(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValueInjectedIntInjector : ValueInjector!int
|
class ValueInjectedIntInjector : ValueInjector!int {
|
||||||
{
|
|
||||||
@Value("five")
|
@Value("five")
|
||||||
public int count = 0;
|
public int count = 0;
|
||||||
|
|
||||||
public override int get(string key)
|
public override int get(string key) {
|
||||||
{
|
if (key == "five") {
|
||||||
if (key == "five")
|
|
||||||
{
|
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,14 +595,11 @@ version (unittest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DependencyValueInjectedIntInjector : ValueInjector!int
|
class DependencyValueInjectedIntInjector : ValueInjector!int {
|
||||||
{
|
|
||||||
@Autowire public ConfigWithDefaults config;
|
@Autowire public ConfigWithDefaults config;
|
||||||
|
|
||||||
public override int get(string key)
|
public override int get(string key) {
|
||||||
{
|
if (key == "conf.missing") {
|
||||||
if (key == "conf.missing")
|
|
||||||
{
|
|
||||||
return 8899;
|
return 8899;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,57 +607,46 @@ version (unittest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TemplatedComponent(T)
|
class TemplatedComponent(T) {
|
||||||
{
|
|
||||||
@Autowire T instance;
|
@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;
|
public TemplatedComponent!T dependency;
|
||||||
|
|
||||||
this(TemplatedComponent!T assignedDependency)
|
this(TemplatedComponent!T assignedDependency) {
|
||||||
{
|
|
||||||
this.dependency = 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
|
@Autowire
|
||||||
public int lala()
|
public int lala() {
|
||||||
{
|
|
||||||
return 42;
|
return 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowire
|
@Autowire
|
||||||
public int lala(int valla)
|
public int lala(int valla) {
|
||||||
{
|
|
||||||
return valla;
|
return valla;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,5 @@
|
||||||
* The full terms of the license can be found in the LICENSE file.
|
* The full terms of the license can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,32 +10,26 @@ import poodinis.test.testclasses;
|
||||||
|
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest) {
|
||||||
{
|
|
||||||
|
|
||||||
struct LocalStruct
|
struct LocalStruct {
|
||||||
{
|
|
||||||
bool wasInjected = false;
|
bool wasInjected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalStructInjector : ValueInjector!LocalStruct
|
class LocalStructInjector : ValueInjector!LocalStruct {
|
||||||
{
|
public override LocalStruct get(string key) {
|
||||||
public override LocalStruct get(string key)
|
|
||||||
{
|
|
||||||
auto data = LocalStruct(true);
|
auto data = LocalStruct(true);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalClassWithStruct
|
class LocalClassWithStruct {
|
||||||
{
|
|
||||||
@Value("")
|
@Value("")
|
||||||
public LocalStruct localStruct;
|
public LocalStruct localStruct;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values
|
// Test injection of values
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!MyConfig;
|
container.register!MyConfig;
|
||||||
container.register!(ValueInjector!int, IntInjector);
|
container.register!(ValueInjector!int, IntInjector);
|
||||||
|
@ -49,8 +43,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values throws exception when injector is not there
|
// Test injection of values throws exception when injector is not there
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!MyConfig;
|
container.register!MyConfig;
|
||||||
assertThrown!ResolveException(container.resolve!MyConfig);
|
assertThrown!ResolveException(container.resolve!MyConfig);
|
||||||
|
@ -59,8 +52,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injection of values with defaults
|
// Test injection of values with defaults
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithDefaults;
|
container.register!ConfigWithDefaults;
|
||||||
container.register!(ValueInjector!int, DefaultIntInjector);
|
container.register!(ValueInjector!int, DefaultIntInjector);
|
||||||
|
@ -70,8 +62,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mandatory injection of values which are available
|
// Test mandatory injection of values which are available
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithMandatory;
|
container.register!ConfigWithMandatory;
|
||||||
container.register!(ValueInjector!int, MandatoryAvailableIntInjector);
|
container.register!(ValueInjector!int, MandatoryAvailableIntInjector);
|
||||||
|
@ -81,8 +72,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mandatory injection of values which are not available
|
// Test mandatory injection of values which are not available
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithMandatory;
|
container.register!ConfigWithMandatory;
|
||||||
container.register!(ValueInjector!int, MandatoryUnavailableIntInjector);
|
container.register!(ValueInjector!int, MandatoryUnavailableIntInjector);
|
||||||
|
@ -92,8 +82,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting dependencies within value injectors
|
// Test injecting dependencies within value injectors
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto dependency = new Dependency();
|
auto dependency = new Dependency();
|
||||||
container.register!Dependency.existingInstance(dependency);
|
container.register!Dependency.existingInstance(dependency);
|
||||||
|
@ -104,8 +93,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test injecting circular dependencies within value injectors
|
// Test injecting circular dependencies within value injectors
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!int, CircularIntInjector);
|
container.register!(ValueInjector!int, CircularIntInjector);
|
||||||
auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int);
|
auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int);
|
||||||
|
@ -115,8 +103,7 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test value injection within value injectors
|
// Test value injection within value injectors
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!int, ValueInjectedIntInjector);
|
container.register!(ValueInjector!int, ValueInjectedIntInjector);
|
||||||
auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int);
|
auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int);
|
||||||
|
@ -125,21 +112,19 @@ version (unittest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test value injection within dependencies of value injectors
|
// Test value injection within dependencies of value injectors
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ConfigWithDefaults;
|
container.register!ConfigWithDefaults;
|
||||||
|
|
||||||
container.register!(ValueInjector!int, DependencyValueInjectedIntInjector);
|
container.register!(ValueInjector!int, DependencyValueInjectedIntInjector);
|
||||||
auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(
|
auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(
|
||||||
ValueInjector!int);
|
ValueInjector!int);
|
||||||
|
|
||||||
assert(injector.config.noms == 8899);
|
assert(injector.config.noms == 8899);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test resolving locally defined struct injector (github issue #20)
|
// Test resolving locally defined struct injector (github issue #20)
|
||||||
unittest
|
unittest {
|
||||||
{
|
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!(ValueInjector!LocalStruct, LocalStructInjector);
|
container.register!(ValueInjector!LocalStruct, LocalStructInjector);
|
||||||
container.register!LocalClassWithStruct;
|
container.register!LocalClassWithStruct;
|
||||||
|
|
Loading…
Reference in a new issue