1 /**********************************************************\ 2 | | 3 | hprose | 4 | | 5 | Official WebSite: http://www.hprose.com/ | 6 | http://www.hprose.org/ | 7 | | 8 \**********************************************************/ 9 10 /**********************************************************\ 11 * * 12 * hprose/io/classmanager.d * 13 * * 14 * hprose classmanager library for D. * 15 * * 16 * LastModified: Jan 3, 2016 * 17 * Author: Ma Bingyao <andot@hprose.com> * 18 * * 19 \**********************************************************/ 20 21 module hprose.io.classmanager; 22 23 import hprose.io.common; 24 import hprose.io.reader; 25 import std.stdio; 26 import std.traits; 27 import std.variant; 28 import std.typecons; 29 30 package interface Unserializer { 31 Variant get(); 32 void setRef(); 33 void setField(string name); 34 } 35 36 private synchronized class classmanager { 37 private { 38 TypeInfo[string] nameCache; 39 string[TypeInfo] typeCache; 40 Unserializer delegate(Reader reader)[TypeInfo] unserializerCache; 41 } 42 string register(T)(string name) { 43 if (name !in nameCache) { 44 nameCache[name] = cast(shared)typeid(Unqual!T); 45 typeCache[typeid(Unqual!T)] = name; 46 unserializerCache[typeid(Unqual!T)] = delegate(Reader reader) { 47 class UnserializerImpl: Unserializer { 48 private { 49 Unqual!T value = make!(Unqual!T)(); 50 @safe void delegate()[string] setters; 51 } 52 private void genSetters(alias fieldList)() { 53 static if (fieldList.length > 0) { 54 enum f = fieldList[0]; 55 setters[f] = delegate() { 56 __traits(getMember, value, f) = reader.unserialize!(typeof(__traits(getMember, value, f)))(); 57 }; 58 static if (fieldList.length > 1) { 59 genSetters!(tuple(fieldList[1..$]))(); 60 } 61 } 62 } 63 this() { 64 genSetters!(getSerializableFields!(Unqual!T))(); 65 } 66 Variant get() { 67 return Variant(value); 68 } 69 void setRef() { 70 static if (is(T == struct)) { 71 reader.setRef(null); 72 } 73 else { 74 reader.setRef(value); 75 } 76 } 77 void setField(string name) { 78 if (name in setters) { 79 setters[name](); 80 } 81 else { 82 reader.unserialize!Variant(); 83 } 84 } 85 } 86 return new UnserializerImpl(); 87 }; 88 } 89 return name; 90 } 91 TypeInfo getClass(string name) { 92 return (cast(TypeInfo[string])nameCache).get(name, null); 93 } 94 string getAlias(T)() { 95 return (cast(string[TypeInfo])typeCache).get(typeid(Unqual!T), register!T(Unqual!T.stringof)); 96 } 97 package Unserializer getUnserializer(TypeInfo t, Reader reader) { 98 if (t in unserializerCache) { 99 return unserializerCache[t](reader); 100 } 101 return null; 102 } 103 } 104 105 static shared classmanager ClassManager = new shared classmanager(); 106 107 private { 108 class MyClass { int a; } 109 class MyClass2 { int a; } 110 } 111 112 unittest { 113 ClassManager.register!(MyClass)("Apple"); 114 assert(ClassManager.getAlias!(MyClass) == "Apple"); 115 assert(ClassManager.getAlias!(MyClass2) == "MyClass2"); 116 assert(ClassManager.getClass("Apple") is typeid(MyClass)); 117 assert(ClassManager.getClass("MyClass2") is typeid(MyClass2)); 118 }