1 module jar; 2 3 import std.array; 4 import std.typecons; 5 6 /// a container for registered types 7 class Jar { 8 private Object[][TypeInfo] _instance_registry; 9 10 /// register a type instance 11 public T register(T)(T instance) { 12 auto type = typeid(instance); 13 if (type !in _instance_registry) { 14 _instance_registry[type] = new Object[0]; 15 } 16 _instance_registry[type] ~= instance; 17 return instance; 18 } 19 20 /// resolve all matching type instances 21 public T[] resolve_all(T)() { 22 auto type = typeid(T); 23 if (type in _instance_registry) { 24 Appender!(T[]) resolved; 25 foreach (item; _instance_registry[type]) { 26 resolved ~= cast(T) item; 27 } 28 return resolved.data; 29 } 30 return new T[0]; 31 } 32 33 /// resolve first matching type instance 34 public Nullable!T resolve(T)() { 35 auto items = resolve_all!T(); 36 if (items.length > 0) { 37 return Nullable!T(items[0]); 38 } 39 return Nullable!T.init; 40 } 41 } 42 43 unittest { 44 class Cookie { 45 bool delicious = true; 46 } 47 48 auto jar = new Jar(); 49 50 auto c1 = new Cookie(); 51 jar.register(c1); 52 auto r1 = jar.resolve!Cookie(); 53 assert(!r1.isNull, "resolved item was null"); 54 assert(r1.get() == c1, "resolved item did not match"); 55 56 auto c2 = new Cookie(); 57 jar.register(c2); 58 59 const auto cookies = jar.resolve_all!Cookie(); 60 assert(cookies.length == 2, "mismatch in number of registered items"); 61 }