随笔-341  评论-2670  文章-0  trackbacks-0
    所谓的反射当然不是自动化的,而是需要自己打标记的。下面会展示两份文件,告诉大家我这个做了一半的反射是怎么工作的。写这个东西的主要目的是,将来可以实现序列化,譬如说序列化到流,或者序列化到XML文件,或者做其他的事情等等(譬如说使用类名创建对象并进行修改)。

    首先是运行结果。下面的结果是console application窗口上打印的。因为太长所以没截图。我创建了三个对象,然后使用反射将他们的内容打印了出来:
  1 Cat {
  2   BodyLength = 50
  3   TailLength = 30
  4   FingerCount = 18
  5   Age = 10
  6   Weight = 100
  7 }
  8 Fish {
  9   MaxDepth = 3000.0
 10   Length = 25
 11   Age = 20
 12   Weight = 200
 13 }
 14 Bird {
 15   CanFly = true
 16   Name = Jack
 17   Age = 30
 18   Weight = 300
 19 }
 20 Human {
 21   Name = 囧Smith
 22   MainPat = Cat {
 23     BodyLength = 40
 24     TailLength = 20
 25     FingerCount = 18
 26     Age = 5
 27     Weight = 150
 28   }
 29   MainTransportation = Bird {
 30     CanFly = true
 31     Name = Red Dragon
 32     Age = 3000
 33     Weight = 300
 34   }
 35   OtherPats = VL_AutoPtr<Animal>[4] {
 36     item[0= Cat {
 37       BodyLength = 50
 38       TailLength = 30
 39       FingerCount = 18
 40       Age = 10
 41       Weight = 100
 42     }
 43     item[1= Fish {
 44       MaxDepth = 3000.0
 45       Length = 25
 46       Age = 20
 47       Weight = 200
 48     }
 49     item[2= Bird {
 50       CanFly = true
 51       Name = Jack
 52       Age = 30
 53       Weight = 300
 54     }
 55     item[3= <NULL>
 56   }
 57   OtherTranspotations = Bird[3] {
 58     item[0= Bird {
 59       CanFly = true
 60       Name = Blue Dragon 1
 61       Age = 3000
 62       Weight = 300
 63     }
 64     item[1= Bird {
 65       CanFly = true
 66       Name = Blue Dragon 2
 67       Age = 3100
 68       Weight = 300
 69     }
 70     item[2= Bird {
 71       CanFly = true
 72       Name = Blue Dragon 3
 73       Age = 3200
 74       Weight = 300
 75     }
 76   }
 77   OtherPatsList = VL_List<VL_AutoPtr<Animal> , false> {
 78     item[0= Cat {
 79       BodyLength = 50
 80       TailLength = 30
 81       FingerCount = 18
 82       Age = 10
 83       Weight = 100
 84     }
 85     item[1= Fish {
 86       MaxDepth = 3000.0
 87       Length = 25
 88       Age = 20
 89       Weight = 200
 90     }
 91     item[2= Bird {
 92       CanFly = true
 93       Name = Jack
 94       Age = 30
 95       Weight = 300
 96     }
 97   }
 98   OtherTranspotationsList = VL_List<Bird , false> {
 99     item[0= Bird {
100       CanFly = true
101       Name = Green Dragon 1
102       Age = 3000
103       Weight = 300
104     }
105     item[1= Bird {
106       CanFly = true
107       Name = Green Dragon 2
108       Age = 3010
109       Weight = 300
110     }
111     item[2= Bird {
112       CanFly = true
113       Name = Green Dragon 3
114       Age = 3020
115       Weight = 300
116     }
117   }
118   FingerCount = 20
119   Age = 16
120   Weight = 2000
121 }
122 

    下面是main函数的代码。这里声明了几个类,然后标记了一下感兴趣的成员:
  1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
  2 #include "..\..\..\..\VL++\Library\Data\Inspector\VL_ObjectInspector.h"
  3 #include "..\..\..\..\VL++\Library\Data\Inspector\VL_ObjectStrconv.h"
  4 
  5 using namespace vl;
  6 using namespace vl::platform;
  7 using namespace vl::inspector;
  8 
  9 class Animal : public VL_Base
 10 {
 11 public:
 12     VInt                Age;
 13     VInt                Weight;
 14 };
 15 
 16 class Mammalian : public Animal
 17 {
 18 public:
 19     VInt                FingerCount;
 20 };
 21 
 22 class Cat : public Mammalian
 23 {
 24 public:
 25     VInt                BodyLength;
 26     VInt                TailLength;
 27 
 28     Cat()
 29     {
 30         Age=10;
 31         Weight=100;
 32         FingerCount=18;
 33         BodyLength=50;
 34         TailLength=30;
 35     }
 36 };
 37 
 38 class Fish : public Animal
 39 {
 40 public:
 41     VDouble                MaxDepth;
 42     VInt                Length;
 43 
 44     Fish()
 45     {
 46         Age=20;
 47         Weight=200;
 48         MaxDepth=3000;
 49         Length=25;
 50     }
 51 };
 52 
 53 class Bird : public Animal
 54 {
 55 public:
 56     VBool                CanFly;
 57     VUnicodeString        Name;
 58 
 59     Bird()
 60     {
 61         Age=30;
 62         Weight=300;
 63         CanFly=true;
 64         Name=L"Jack";
 65     }
 66 };
 67 
 68 class Human : public Mammalian
 69 {
 70 public:
 71     VUnicodeString                                    Name;
 72     VL_AutoPtr<Animal>                                MainPat;
 73     Bird                                            MainTransportation;
 74     VL_AutoPtr<Animal>                                OtherPats[4];
 75     Bird                                            OtherTranspotations[3];
 76     VL_List<VL_AutoPtr<Animal> , false , Animal*>    OtherPatsList;
 77     VL_List<Bird , false>                            OtherTranspotationsList;
 78 
 79     Human()
 80     {
 81         Age=16;
 82         Weight=2000;
 83         FingerCount=20;
 84         Name=L"囧Smith";
 85 
 86         Cat* cat=new Cat;
 87         cat->Age=5;
 88         cat->Weight=150;
 89         cat->BodyLength=40;
 90         cat->TailLength=20;
 91         MainPat=cat;
 92 
 93         MainTransportation.Name=L"Red Dragon";
 94         MainTransportation.Age=3000;
 95 
 96         OtherPats[0]=new Cat;
 97         OtherPats[1]=new Fish;
 98         OtherPats[2]=new Bird;
 99 
100         for(VInt i=0;i<3;i++)
101         {
102             OtherTranspotations[i].Name=L"Blue Dragon "+VUnicodeString(i+1);
103             OtherTranspotations[i].Age=3000+i*100;
104         }
105 
106         OtherPatsList.Add(new Cat);
107         OtherPatsList.Add(new Fish);
108         OtherPatsList.Add(new Bird);
109 
110         for(VInt i=0;i<3;i++)
111         {
112             OtherTranspotationsList.Add(Bird());
113             OtherTranspotationsList[i].Name=L"Green Dragon "+VUnicodeString(i+1);
114             OtherTranspotationsList[i].Age=3000+i*10;
115         }
116     }
117 };
118 
119 VL_BEGIN_INSPECTOR_DECLARATION
120 
121     VL_BEGIN_BASE_CLASS(Animal)
122         VL_ADD_CLASS_MEMBER(Animal,Age)
123         VL_ADD_CLASS_MEMBER(Animal,Weight)
124     VL_END_CLASS(Animal)
125 
126     VL_BEGIN_SUB_CLASS(Mammalian,Animal)
127         VL_ADD_CLASS_MEMBER(Mammalian,FingerCount)
128     VL_END_CLASS(Mammalian)
129 
130     VL_BEGIN_SUB_CLASS(Cat,Mammalian)
131         VL_ADD_CLASS_MEMBER(Cat,BodyLength)
132         VL_ADD_CLASS_MEMBER(Cat,TailLength)
133     VL_END_CLASS(Cat)
134 
135     VL_BEGIN_SUB_CLASS(Fish,Animal)
136         VL_ADD_CLASS_MEMBER(Fish,MaxDepth)
137         VL_ADD_CLASS_MEMBER(Fish,Length)
138     VL_END_CLASS(Fish)
139 
140     VL_BEGIN_SUB_CLASS(Bird,Animal)
141         VL_ADD_CLASS_MEMBER(Bird,CanFly)
142         VL_ADD_CLASS_MEMBER(Bird,Name)
143     VL_END_CLASS(Bird)
144 
145     VL_BEGIN_SUB_CLASS(Human,Mammalian)
146         VL_ADD_CLASS_MEMBER(Human,Name)
147         VL_ADD_CLASS_MEMBER(Human,MainPat)
148         VL_ADD_CLASS_MEMBER(Human,MainTransportation)
149         VL_ADD_CLASS_MEMBER(Human,OtherPats)
150         VL_ADD_CLASS_MEMBER(Human,OtherTranspotations)
151         VL_ADD_CLASS_MEMBER(Human,OtherPatsList)
152         VL_ADD_CLASS_MEMBER(Human,OtherTranspotationsList)
153     VL_END_CLASS(Human)
154 
155     VL_BEGIN_INSPECTOR_MANAGER(AnimalManager)
156         VL_BIND_INSPECTOR(Animal)
157         VL_BIND_INSPECTOR(Mammalian)
158         VL_BIND_INSPECTOR(Cat)
159         VL_BIND_INSPECTOR(Fish)
160         VL_BIND_INSPECTOR(Bird)
161         VL_BIND_INSPECTOR(Human)
162     VL_END_INSPECTOR_MANAGER
163 
164 VL_END_INSPECTOR_DECLARATION
165 
166 void PrintAnimal(VL_InspectorManager::Ptr Manager , Animal* aAnimal)
167 {
168     VL_InspectorConverterManager Converter;
169     Converter.AddNormalConverter(new VL_InspectorReader);
170 
171     VL_ObjectInspector::Ptr Inspector=Manager->GetInspector(VL_InspectorSelector<Animal>::GetID());
172     GetConsole()->WriteLine(Converter.FindToStringConverter(Inspector)->ConvertToString(Inspector,aAnimal));
173 }
174 
175 void vlmain()
176 {
177     GetConsole()->SetTitle(L"Vczh Library++ 2.0 Type Information Test");
178     GetConsole()->SetTestMemoryLeaks(true);
179     GetConsole()->SetPauseOnExit(true);
180 
181     VL_InspectorManager::Ptr Manager=VL_GET_INSPECTOR_MANAGER(AnimalManager);
182 
183     Cat cat;
184     Fish fish;
185     Bird bird;
186     Human human;
187     PrintAnimal(Manager,&cat);
188     PrintAnimal(Manager,&fish);
189     PrintAnimal(Manager,&bird);
190     PrintAnimal(Manager,&human);
191 }

    最后是一个ConvertToString的函数,来展示如何读取数据的:
 1         VUnicodeString VL_InspectorReader::ConvertToString(VL_ObjectInspector::Ptr Inspector , VPointer Data , VUnicodeString Prefix)
 2         {
 3             if(Data==0)
 4             {
 5                 return L"<NULL>";
 6             }
 7             else if(VL_AutoPtr<VL_StructInspector> Struct=Inspector)
 8             {
 9                 Struct=Struct->GetRealObject(Data);
10                 VUnicodeString String=Struct->GetID()+L" {\r\n";
11                 while(Struct)
12                 {
13                     for(VInt i=0;i<Struct->GetMemberCount();i++)
14                     {
15                         VL_MemberInspector::Ptr Member=Struct->GetMember(i);
16                         String+=Prefix+L"  "+Member->GetMemberName()+L" = ";
17                         String+=ConvertToString(Member->GetMemberInspector(),Member->GetMember(Data),Prefix+L"  ")+L"\r\n";
18                     }
19                     Data=Struct->GetBase(Data);
20                     Struct=Struct->GetBaseInspector();
21                 }
22                 String+=Prefix+L"}";
23                 return String;
24             }
25             else if(VL_AutoPtr<VL_CollectionInspector> Collection=Inspector)
26             {
27                 VUnicodeString String=Collection->GetID()+L" {\r\n";
28                 for(VInt i=0;i<Collection->GetMemberCount(Data);i++)
29                 {
30                     VL_MemberInspector::Ptr Member=Collection->GetMember(i,Data);
31                     String+=Prefix+L"  item["+VUnicodeString(i)+L"] = ";
32                     String+=ConvertToString(Member->GetMemberInspector(),Member->GetMember(Data),Prefix+L"  ")+L"\r\n";
33                 }
34                 String+=Prefix+L"}";
35                 return String;
36             }
37             else
38             {
39                 VL_InspectorConverter::Ptr Converter=FManager->FindToStringConverter(Inspector);
40                 if(Converter)
41                 {
42                     return Converter->ConvertToString(Inspector,Data);
43                 }
44                 else
45                 {
46                     return L"<UNKNOWN>";
47                 }
48             }
49         }
posted on 2009-06-25 06:48 陈梓瀚(vczh) 阅读(3486) 评论(4)  编辑 收藏 引用 所属分类: C++

评论:
# re: 重写了C++的类似反射的工具 2009-06-26 12:38 | XXOOXX
挺好用的東西。
我認為原理就是記住成員的類型和在類中的位置,并對應他們的名字。
然後可以通過名字取到某個類對象的成員。

我是用 &((clsss*)0)->mem; 這樣取成員位置。

  回复  更多评论
  
# re: 重写了C++的类似反射的工具 2009-06-27 07:27 | 陈梓瀚(vczh)
@XXOOXX
是的。  回复  更多评论
  
# re: 重写了C++的类似反射的工具 2009-07-01 22:49 | Gohan
宏里博主应该也用了楼上所说的“&((clsss*)0)->mem”技法了吧?  回复  更多评论
  
# re: 重写了C++的类似反射的工具 2009-07-03 01:15 | 陈梓瀚(vczh)
我其实用的是&class::mem。C++有一些新东西。  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理