mirage-injector/source/poodinis/valueinjector/mirage.d
2023-01-11 02:09:03 +03:00

300 lines
9.9 KiB
D

/**
* Mirage Config value injector for the Poodinis Dependency Injection Framework
* Copyright 2022-2023 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.
*/
module poodinis.valueinjector.mirage;
import poodinis : ValueInjector, DependencyContainer, Value, Autowire, existingInstance;
import mirage : ConfigDictionary, mirageLoadConfig = loadConfig;
import mirage.json : mirageLoadJsonConfig = loadJsonConfig, mirageParseJsonConfig = parseJsonConfig;
import mirage.java : mirageLoadJavaConfig = loadJavaConfig, mirageParseJavaConfig = parseJavaConfig;
import mirage.ini : mirageLoadIniConfig = loadIniConfig, mirageParseIniConfig = parseIniConfig;
class MirageValueInjector(Type) : ValueInjector!Type
{
@Autowire
private ConfigDictionary config;
public override Type get(string key)
{
return config.get!Type(key);
}
}
alias MirageBoolValueInjector = MirageValueInjector!bool;
alias MirageByteValueInjector = MirageValueInjector!byte;
alias MirageUbyteValueInjector = MirageValueInjector!ubyte;
alias MirageCharValueInjector = MirageValueInjector!char;
alias MirageShortValueInjector = MirageValueInjector!short;
alias MirageUshortValueInjector = MirageValueInjector!ushort;
alias MirageWcharValueInjector = MirageValueInjector!wchar;
alias MirageIntValueInjector = MirageValueInjector!int;
alias MirageUintValueInjector = MirageValueInjector!uint;
alias MirageDcharValueInjector = MirageValueInjector!dchar;
alias MirageLongValueInjector = MirageValueInjector!long;
alias MirageUlongValueInjector = MirageValueInjector!ulong;
alias MirageFloatValueInjector = MirageValueInjector!float;
alias MirageDoubleValueInjector = MirageValueInjector!double;
alias MirageRealValueInjector = MirageValueInjector!real;
alias MirageStringValueInjector = MirageValueInjector!string;
/**
* Registers Mirage Config value injectors for all primitive types.
* Params:
* container = Dependency container to register injectors with.
*/
public void registerMirageInjectors(shared(DependencyContainer) container)
{
container.register!(ValueInjector!bool, MirageBoolValueInjector);
container.register!(ValueInjector!byte, MirageByteValueInjector);
container.register!(ValueInjector!ubyte, MirageUbyteValueInjector);
container.register!(ValueInjector!char, MirageCharValueInjector);
container.register!(ValueInjector!short, MirageShortValueInjector);
container.register!(ValueInjector!ushort, MirageUshortValueInjector);
container.register!(ValueInjector!wchar, MirageWcharValueInjector);
container.register!(ValueInjector!int, MirageIntValueInjector);
container.register!(ValueInjector!uint, MirageUintValueInjector);
container.register!(ValueInjector!dchar, MirageDcharValueInjector);
container.register!(ValueInjector!long, MirageLongValueInjector);
container.register!(ValueInjector!ulong, MirageUlongValueInjector);
container.register!(ValueInjector!float, MirageFloatValueInjector);
container.register!(ValueInjector!double, MirageDoubleValueInjector);
container.register!(ValueInjector!real, MirageRealValueInjector);
container.register!(ValueInjector!string, MirageStringValueInjector);
}
/**
* Load config from disk.
* A specific loader will be used based on the file's extension. registerMirageInjectors
* will be called by this function. The loaded ConfigDictionary will be registered and available
* for injection by itself too.
*
* Params:
* container = Dependency container to register config and injectors with.
* configPath = Path to the configuration file.
* Throws: ConfigCreationException when the file's extension is unrecognized.
*/
public void loadConfig(shared(DependencyContainer) container, const string configPath)
{
processConfig(container, configPath, &mirageLoadConfig);
}
/**
* Load a JSON config from disk.
* registerMirageInjectors will be called by this function. The loaded ConfigDictionary will be
* registered and available for injection by itself too.
* Params:
* container = Dependency container to register config and injectors with.
* configPath = Path to the configuration file.
*/
public void loadJsonConfig(shared(DependencyContainer) container, const string configPath)
{
processConfig(container, configPath, &mirageLoadJsonConfig);
}
/**
* Load a Java properties from disk.
* registerMirageInjectors will be called by this function. The loaded ConfigDictionary will be
* registered and available for injection by itself too.
* Params:
* container = Dependency container to register config and injectors with.
* configPath = Path to the configuration file.
*/
public void loadJavaProperties(shared(DependencyContainer) container, const string configPath)
{
processConfig(container, configPath, &mirageLoadJavaConfig);
}
/// ditto
alias loadJavaConfig = loadJavaProperties;
/**
* Load an INI config from disk.
* registerMirageInjectors will be called by this function. The loaded ConfigDictionary will be
* registered and available for injection by itself too.
* Params:
* container = Dependency container to register config and injectors with.
* configPath = Path to the configuration file.
*/
public void loadIniConfig(shared(DependencyContainer) container, const string configPath)
{
processConfig(container, configPath, &mirageLoadIniConfig);
}
/**
* Parse JSON config from the given string.
*
* Params:
* container = Dependency container to register config and injectors with.
* config = Contents of the config to parse.
*/
public void parseJsonConfig(shared(DependencyContainer) container, const string config)
{
processConfig(container, config, &mirageParseJsonConfig);
}
/**
* Parse Java properties from the given string.
*
* Params:
* container = Dependency container to register config and injectors with.
* config = Contents of the properties to parse.
*/
public void parseJavaProperties(shared(DependencyContainer) container, const string properties)
{
processConfig(container, properties, &mirageParseJavaConfig);
}
/// ditto
alias parseJavaConfig = parseJavaProperties;
/**
* Parse INI config from the given string.
*
* Params:
* container = Dependency container to register config and injectors with.
* config = Contents of the config to parse.
*/
public void parseIniConfig(shared(DependencyContainer) container, const string config)
{
processConfig(container, config, &mirageParseIniConfig);
}
private void processConfig(
shared(DependencyContainer) container,
const string configProcParam,
ConfigDictionary function(const string configProcParam) procFunc
)
{
container.registerMirageInjectors;
auto config = procFunc(configProcParam);
container.register!ConfigDictionary.existingInstance(config);
}
version (unittest)
{
class TestClass
{
@Value("horse.name")
public string horseName;
@Value("horse.children")
public uint horseChildCount;
}
@("Register primitive value injectors")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.registerMirageInjectors;
}
@("Load config file using generic loader")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.loadConfig("testfiles/horses.ini");
auto config = dependencies.resolve!ConfigDictionary;
assert(config.get("horse.name") == "Breeeeeezer");
}
@("Inject loaded config into class values")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.loadConfig("testfiles/horses.ini");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Breeeeeezer");
assert(testClass.horseChildCount == 4);
}
@("Load JSON config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.loadJsonConfig("testfiles/horses.json");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Maaarrrilll");
}
@("Parse JSON config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.parseJsonConfig("
{
\"horse\": {
\"name\": \"Stooommmmmyyyy\",
\"children\": 56
}
}
");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Stooommmmmyyyy");
}
@("Load Java config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.loadJavaConfig("testfiles/horses.properties");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Beaaaaaaan");
}
@("Parse Java config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.parseJavaConfig("
horse.name = Bruuuuuhhhhlleeee
horse.children = 909
");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Bruuuuuhhhhlleeee");
}
@("Load INI config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.loadIniConfig("testfiles/horses.ini");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Breeeeeezer");
}
@("Parse INI config")
unittest
{
auto dependencies = new shared DependencyContainer;
dependencies.register!TestClass;
dependencies.parseIniConfig("
[horse]
name = \"Raaaammmmmaaaaaah\"
children = 34
");
auto testClass = dependencies.resolve!TestClass;
assert(testClass.horseName == "Raaaammmmmaaaaaah");
}
}