1 module classutil;
2 /** 
3  * Checks if the object instance have implemented the given interface or not.
4  * Intended for avoiding typecasting incidents.
5  * Params:
6  *   o = The object instance to be tested.
7  * Template params:
8  *   I = The interface type to check for.
9  * Returns: True if interface is implemented in the object instance, false otherwise.
10  */
11 public bool isInterface(I)(Object o) @safe nothrow {
12     for (TypeInfo_Class crnt = o.classinfo ; crnt !is null ; crnt = crnt.base) {
13         foreach (Interface key; crnt.interfaces) {
14             if (key.classinfo == I.classinfo)
15                 return true;
16         }
17     }
18     return false;
19 }
20 /** 
21  * Check if the object instance is of a certain class, inherited from it, or not.
22  * Intended for avoiding typecasting incidents.
23  * Params:
24  *   o = The object instance to be tested.
25  * Template params:
26  *   C = The class type to check for.
27  * Returns: True if the class is of a given type or have inherited from it, false otherwise.
28  */
29 public bool isClass(C)(Object o) @safe nothrow {
30     import std.string;
31     for (TypeInfo_Class crnt = o.classinfo ; crnt !is null ; crnt = crnt.base) {
32         if (crnt == C.classinfo)
33             return true;
34     }
35     return false;
36 }
37 /** 
38  * Check if the type that has a static classinfo property is implemented by the object instance or not.
39  * Intended for avoiding typecasting incidents.
40  * Params:
41  *   o = The object instance to be tested.
42  * Template params:
43  *   T = The class or interface type to check for.
44  * Returns: True if the class is of a given type or have inherited from it, false otherwise.
45  */
46 public bool isImplemented(T)(Object o) @safe nothrow {
47     for (TypeInfo_Class crnt = o.classinfo ; crnt !is null ; crnt = crnt.base) {
48         if (crnt == T.classinfo)
49             return true;
50         foreach (Interface key; crnt.interfaces) {
51             if (key.classinfo == T.classinfo)
52                 return true;
53         }
54     }
55     return false;
56 }
57 unittest {
58     interface I0 {}
59     interface I1 {}
60     interface I2 {}
61     class C0 : I0 {
62         this() {}
63     }
64     class C1 : C0, I1 {
65         this() {}
66     }
67     Object test0 = new C0();
68     Object test1 = new C1();
69     assert(isInterface!I0(test0));
70     assert(!isInterface!I1(test0));
71     assert(!isInterface!I2(test0));
72     assert(isInterface!I0(test1));
73     assert(isInterface!I1(test1));
74     assert(!isInterface!I2(test1));
75     assert(isClass!C0(test0));
76     assert(isClass!C0(test1));
77     assert(!isClass!C1(test0));
78     assert(isClass!C1(test1));
79     assert(isImplemented!C0(test0));
80     assert(!isImplemented!C1(test0));
81 }