Move factory stuff to own module

This commit is contained in:
Mike Bierlee 2016-08-17 20:44:36 +02:00
parent ccdef46dde
commit 44e77aff9c
7 changed files with 141 additions and 108 deletions

View file

@ -19,6 +19,7 @@ module poodinis.autowire;
import poodinis.container; import poodinis.container;
import poodinis.registration; import poodinis.registration;
import poodinis.factory;
import std.exception; import std.exception;
import std.stdio; import std.stdio;

View file

@ -15,6 +15,7 @@ module poodinis.context;
import poodinis.container; import poodinis.container;
import poodinis.registration; import poodinis.registration;
import poodinis.factory;
import std.traits; import std.traits;

65
source/poodinis/factory.d Normal file
View file

@ -0,0 +1,65 @@
/**
* This module contains instance factory facilities
*
* Authors:
* Mike Bierlee, m.bierlee@lostmoment.com
* Copyright: 2014-2016 Mike Bierlee
* License:
* This software is licensed under the terms of the MIT license.
* The full terms of the license can be found in the LICENSE file.
*/
module poodinis.factory;
import std.typecons;
import std.exception;
debug {
import std.string;
import std.stdio;
}
alias CreatesSingleton = Flag!"CreatesSingleton";
alias InstanceFactoryMethod = Object delegate();
class InstanceCreationException : Exception {
this(string message, string file = __FILE__, size_t line = __LINE__) {
super(message, file, line);
}
}
class InstanceFactory {
private TypeInfo_Class instanceType = null;
private Object instance = null;
private CreatesSingleton createsSingleton;
private InstanceFactoryMethod factoryMethod;
this(TypeInfo_Class instanceType, CreatesSingleton createsSingleton = CreatesSingleton.yes, Object existingInstance = null, InstanceFactoryMethod factoryMethod = null) {
this.instanceType = instanceType;
this.createsSingleton = existingInstance !is null ? CreatesSingleton.yes : createsSingleton;
this.instance = existingInstance;
this.factoryMethod = factoryMethod !is null ? factoryMethod : &this.createInstance;
}
public Object getInstance() {
if (createsSingleton && instance !is null) {
debug(poodinisVerbose) {
writeln(format("DEBUG: Existing instance returned of type %s", instanceType.toString()));
}
return instance;
}
debug(poodinisVerbose) {
writeln(format("DEBUG: Creating new instance of type %s", instanceType.toString()));
}
instance = factoryMethod();
return instance;
}
private Object createInstance() {
enforce!InstanceCreationException(instanceType, "Instance type is not defined, cannot create instance without knowing its type.");
return instanceType.create();
}
}

View file

@ -15,3 +15,4 @@ public import poodinis.autowire;
public import poodinis.container; public import poodinis.container;
public import poodinis.registration; public import poodinis.registration;
public import poodinis.context; public import poodinis.context;
public import poodinis.factory;

View file

@ -14,20 +14,7 @@
module poodinis.registration; module poodinis.registration;
import poodinis.container; import poodinis.container;
import poodinis.factory;
import std.typecons;
import std.exception;
debug {
import std.stdio;
import std.string;
}
class InstanceCreationException : Exception {
this(string message, string file = __FILE__, size_t line = __LINE__) {
super(message, file, line);
}
}
class Registration { class Registration {
private TypeInfo _registeredType = null; private TypeInfo _registeredType = null;
@ -74,45 +61,6 @@ class Registration {
} }
} }
alias CreatesSingleton = Flag!"CreatesSingleton";
alias InstanceFactoryMethod = Object delegate();
class InstanceFactory {
private TypeInfo_Class instanceType = null;
private Object instance = null;
private CreatesSingleton createsSingleton;
private InstanceFactoryMethod factoryMethod;
this(TypeInfo_Class instanceType, CreatesSingleton createsSingleton = CreatesSingleton.yes, Object existingInstance = null, InstanceFactoryMethod factoryMethod = null) {
this.instanceType = instanceType;
this.createsSingleton = existingInstance !is null ? CreatesSingleton.yes : createsSingleton;
this.instance = existingInstance;
this.factoryMethod = factoryMethod !is null ? factoryMethod : &this.createInstance;
}
public Object getInstance() {
if (createsSingleton && instance !is null) {
debug(poodinisVerbose) {
writeln(format("DEBUG: Existing instance returned of type %s", instanceType.toString()));
}
return instance;
}
debug(poodinisVerbose) {
writeln(format("DEBUG: Creating new instance of type %s", instanceType.toString()));
}
instance = factoryMethod();
return instance;
}
private Object createInstance() {
enforce!InstanceCreationException(instanceType, "Instance type is not defined, cannot create instance without knowing its type.");
return instanceType.create();
}
}
/** /**
* Scopes registrations to return the same instance every time a given registration is resolved. * Scopes registrations to return the same instance every time a given registration is resolved.
* *

View file

@ -0,0 +1,72 @@
/**
* Poodinis Dependency Injection Framework
* Copyright 2014-2016 Mike Bierlee
* This software is licensed under the terms of the MIT license.
* The full terms of the license can be found in the LICENSE file.
*/
import poodinis;
version(unittest) {
interface TestInterface {}
class TestImplementation : TestInterface {
public string someContent = "";
}
// Test instance factory with singletons
unittest {
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.yes, null);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne !is null, "Created factory instance is null");
assert(instanceOne is instanceTwo, "Created factory instance is not the same");
}
// Test instance factory with new instances
unittest {
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.no, null);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne !is null, "Created factory instance is null");
assert(instanceOne !is instanceTwo, "Created factory instance is the same");
}
// Test instance factory with existing instances
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.yes, existingInstance);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne is existingInstance, "Created factory instance is not the existing instance");
assert(instanceTwo is existingInstance, "Created factory instance is not the existing instance when called again");
}
// Test instance factory with existing instances when setting singleton flag to "no"
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.no, existingInstance);
auto instance = factory.getInstance();
assert(instance is existingInstance, "Created factory instance is not the existing instance");
}
// Test creating instance using custom factory method
unittest {
Object factoryMethod() {
auto instance = new TestImplementation();
instance.someContent = "Ducks!";
return instance;
}
auto factory = new InstanceFactory(null, CreatesSingleton.yes, null, &factoryMethod);
auto instance = cast(TestImplementation) factory.getInstance();
assert(instance !is null, "No instance was created by factory or could not be cast to expected type");
assert(instance.someContent == "Ducks!");
}
}

View file

@ -65,59 +65,4 @@ version(unittest) {
assert(firstInstance is secondInstance); assert(firstInstance is secondInstance);
} }
// Test instance factory with singletons
unittest {
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.yes, null);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne !is null, "Created factory instance is null");
assert(instanceOne is instanceTwo, "Created factory instance is not the same");
}
// Test instance factory with new instances
unittest {
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.no, null);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne !is null, "Created factory instance is null");
assert(instanceOne !is instanceTwo, "Created factory instance is the same");
}
// Test instance factory with existing instances
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.yes, existingInstance);
auto instanceOne = factory.getInstance();
auto instanceTwo = factory.getInstance();
assert(instanceOne is existingInstance, "Created factory instance is not the existing instance");
assert(instanceTwo is existingInstance, "Created factory instance is not the existing instance when called again");
}
// Test instance factory with existing instances when setting singleton flag to "no"
unittest {
auto existingInstance = new TestImplementation();
auto factory = new InstanceFactory(typeid(TestImplementation), CreatesSingleton.no, existingInstance);
auto instance = factory.getInstance();
assert(instance is existingInstance, "Created factory instance is not the existing instance");
}
// Test creating instance using custom factory method
unittest {
Object factoryMethod() {
auto instance = new TestImplementation();
instance.someContent = "Ducks!";
return instance;
}
auto factory = new InstanceFactory(null, CreatesSingleton.yes, null, &factoryMethod);
auto instance = cast(TestImplementation) factory.getInstance();
assert(instance !is null, "No instance was created by factory or could not be cast to expected type");
assert(instance.someContent == "Ducks!");
}
} }