GacUI从pdb生成反射和dll接口首战告捷

GacUI从pdb生成反射和dll接口首战告捷
    从pdb读取类声明花了很久,从类声明产生反射和dll接口花的时间更久啊,很多细节问题需要解决。文章的代码已经保存在了 Vczh Library++3.0(\Tools\Release\SideProjects\GacUI\GacUI.sln)。

    反射和dll接口的工作进行了一半。现在把类、函数、属性和各种类型都声称了出来,但是还欠缺函数的实现。反射使用了lazy的做法,当访问到一个Type的成员的时候,才会对Type进行初始化。不过初始化的内容也很简单,只是把一些对方放倒一个列表里面,从而当你想知道一个Type有哪些属性和函数什么的可以很快查出来。dll的接口也差不多。现在分别展示反射和dll接口的代码。首先是反射的:

    下面是GuiBoundsComposition类型的反射。我们可以看到gacui_tpimp_GuiBoundsComposition继承自了TypeDescriptor。当我们调用GetTypeProvider->FindType(L"GuiBoundsComposition")->GetTypeDescriptor()的时候,就会返回下面的这个对象。
  1  class  gacui_tpimp_GuiBoundsComposition :  public  TypeDescriptor
  2  {
  3  protected :
  4  void  FillTypeContent()
  5  {
  6      AddBaseType((gacui_tpimp_type_cache_table.cache_GuiGraphicsSite));
  7      AddConstructor(
  8          ( new  MethodDescriptor(L " GuiBoundsComposition " , IMemberDescriptor::Normal))
  9           -> ReturnType((gacui_tpimp_type_cache_table.cache_GuiBoundsComposition) -> GetPointerType())
 10           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_GuiBoundsComposition_0))
 11      );
 12      AddMethod(
 13          ( new  MethodDescriptor(L " GetAffectionFromParent " , IMemberDescriptor::Virtual))
 14           -> ReturnType((gacui_tpimp_type_cache_table.cache_GuiGraphicsComposition_member_ParentSizeAffection))
 15           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_GetAffectionFromParent_1))
 16      );
 17      AddMethod(
 18          ( new  MethodDescriptor(L " GetPreferredBounds " , IMemberDescriptor::Virtual))
 19           -> ReturnType((gacui_tpimp_type_cache_table.cache_Rect))
 20           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_GetPreferredBounds_2))
 21      );
 22      AddMethod(
 23          ( new  MethodDescriptor(L " GetBounds " , IMemberDescriptor::Virtual))
 24           -> ReturnType((gacui_tpimp_type_cache_table.cache_Rect))
 25           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_GetBounds_3))
 26      );
 27      AddMethod(
 28          ( new  MethodDescriptor(L " ClearAlignmentToParent " , IMemberDescriptor::Normal))
 29           -> ReturnType((gacui_tpimp_type_cache_table.primary_Void))
 30           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_ClearAlignmentToParent_4))
 31      );
 32      AddMethod(
 33          ( new  MethodDescriptor(L " IsAlignedToParent " , IMemberDescriptor::Normal))
 34           -> ReturnType((gacui_tpimp_type_cache_table.primary_Bool))
 35           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_IsAlignedToParent_5))
 36      );
 37      AddMethod(
 38          ( new  MethodDescriptor(L " operator= " , IMemberDescriptor::Normal))
 39           -> ReturnType((gacui_tpimp_type_cache_table.cache_GuiBoundsComposition) -> GetReferenceType())
 40           -> Parameter(L " value " , (gacui_tpimp_type_cache_table.cache_GuiBoundsComposition) -> GetConstReferenceType())
 41           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_operator_assign_6))
 42      );
 43      AddMethod(
 44          ( new  MethodDescriptor(L " SetBounds " , IMemberDescriptor::Normal))
 45           -> ReturnType((gacui_tpimp_type_cache_table.primary_Void))
 46           -> Parameter(L " value " , (gacui_tpimp_type_cache_table.cache_Rect))
 47           -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_SetBounds_7))
 48      );
 49      AddProperty(
 50          ( new  PropertyDescriptor(L " AlignmentToParent " , IMemberDescriptor::Normal))
 51           -> PropertyType((gacui_tpimp_type_cache_table.cache_Margin))
 52           -> Getter(
 53              ( new  MethodDescriptor(L " GetAlignmentToParent " , IMemberDescriptor::Normal))
 54               -> ReturnType((gacui_tpimp_type_cache_table.cache_Margin))
 55               -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_GetAlignmentToParent_8))
 56          )
 57           -> Setter(
 58              ( new  MethodDescriptor(L " SetAlignmentToParent " , IMemberDescriptor::Normal))
 59               -> ReturnType((gacui_tpimp_type_cache_table.primary_Void))
 60               -> Parameter(L " value " , (gacui_tpimp_type_cache_table.cache_Margin))
 61               -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_SetAlignmentToParent_9))
 62          )
 63      );
 64      AddProperty(
 65          ( new  PropertyDescriptor(L " BoundsChanged " , IMemberDescriptor::Normal))
 66           -> PropertyType((gacui_tpimp_type_cache_table.cache_GuiGraphicsEvent_of_GuiEventArgs))
 67           -> Getter(
 68              ( new  MethodDescriptor(L " get_BoundsChanged " , IMemberDescriptor::Normal))
 69               -> ReturnType((gacui_tpimp_type_cache_table.cache_GuiGraphicsEvent_of_GuiEventArgs))
 70               -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_get_BoundsChanged_10))
 71          )
 72           -> Setter(
 73              ( new  MethodDescriptor(L " set_BoundsChanged " , IMemberDescriptor::Normal))
 74               -> ReturnType((gacui_tpimp_type_cache_table.primary_Void))
 75               -> Parameter(L " value " , (gacui_tpimp_type_cache_table.cache_GuiGraphicsEvent_of_GuiEventArgs))
 76               -> Handler(MethodDescriptor::HandlerFuncType( & gacui_tpimp_GuiBoundsComposition::method_handler_set_BoundsChanged_11))
 77          )
 78      );
 79  }
 80              
 81  private :
 82                  
 83  static  DescriptableValue method_handler_GuiBoundsComposition_0( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
 84  {
 85       throw   0 ;
 86  }
 87                  
 88  static  DescriptableValue method_handler_GetAffectionFromParent_1( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
 89  {
 90       throw   0 ;
 91  }
 92                  
 93  static  DescriptableValue method_handler_GetPreferredBounds_2( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
 94  {
 95       throw   0 ;
 96  }
 97                  
 98  static  DescriptableValue method_handler_GetBounds_3( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
 99  {
100       throw   0 ;
101  }
102                  
103  static  DescriptableValue method_handler_ClearAlignmentToParent_4( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
104  {
105       throw   0 ;
106  }
107                  
108  static  DescriptableValue method_handler_IsAlignedToParent_5( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
109  {
110       throw   0 ;
111  }
112                  
113  static  DescriptableValue method_handler_operator_assign_6( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
114  {
115       throw   0 ;
116  }
117                  
118  static  DescriptableValue method_handler_SetBounds_7( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
119  {
120       throw   0 ;
121  }
122                  
123  static  DescriptableValue method_handler_GetAlignmentToParent_8( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
124  {
125       throw   0 ;
126  }
127                  
128  static  DescriptableValue method_handler_SetAlignmentToParent_9( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
129  {
130       throw   0 ;
131  }
132                  
133  static  DescriptableValue method_handler_get_BoundsChanged_10( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
134  {
135       throw   0 ;
136  }
137                  
138  static  DescriptableValue method_handler_set_BoundsChanged_11( const  DescriptableValue &  thisObject,  const  collections::IReadonlyList < DescriptableValue >&  parameters)
139  {
140       throw   0 ;
141  }
142              
143  public :
144  };

    如果反射出来的函数不能被调用那自然是没有意义的,所以AddMethod的时候会提供一个handler,而handler就是下面的静态成员函数了。静态成员函数的实现就是从thisObject拿到GuiBoundsComposition*之后,去调用对应的函数。这个部分是可以自动生成的,只是现在还没写完。

    反射只是一部分,dll的接口也要生成,因为GacUI的实现使用了很多模板和自定义异常,而模板和异常跨越dll边界是很危险的,所以需要用自动生成的代码来把这些东西隔离开(包括一场),从而实现安全调用。下面就是自动生成的dll接口代码,而同样,函数也暂时没有实现的内容:
 1  /* **********************************************************************
 2  GuiBoundsComposition
 3  ********************************************************************** */
 4 
 5       class  GACUI_API GuiBoundsComposition :  public  GuiGraphicsSite
 6      {
 7       public :
 8      
 9       public :
10          
11           static  rptr < GuiBoundsComposition >  Create();
12          
13          GuiGraphicsComposition :: ParentSizeAffection GetAffectionFromParent();
14          Rect GetPreferredBounds();
15          Rect GetBounds();
16           void  ClearAlignmentToParent();
17           bool  IsAlignedToParent();
18          rptr < GuiBoundsComposition >   operator = (rptr < GuiBoundsComposition >  value);
19           void  SetBounds(Rect value);
20          
21          Margin GetAlignmentToParent();
22           void  SetAlignmentToParent(Margin value);
23          GuiGraphicsEvent_of_GuiEventArgs on_BoundsChanged();
24          
25      };
26 
27  /* **********************************************************************
28  GuiBoundsComposition
29  ********************************************************************** */
30 
31      rptr < GuiBoundsComposition >  GuiBoundsComposition::Create()
32      {
33           throw   0 ;
34      }
35      
36      GuiGraphicsComposition :: ParentSizeAffection GuiBoundsComposition::GetAffectionFromParent()
37      {
38           throw   0 ;
39      }
40      
41      Rect GuiBoundsComposition::GetPreferredBounds()
42      {
43           throw   0 ;
44      }
45      
46      Rect GuiBoundsComposition::GetBounds()
47      {
48           throw   0 ;
49      }
50      
51       void  GuiBoundsComposition::ClearAlignmentToParent()
52      {
53           throw   0 ;
54      }
55      
56       bool  GuiBoundsComposition::IsAlignedToParent()
57      {
58           throw   0 ;
59      }
60      
61      rptr < GuiBoundsComposition >  GuiBoundsComposition:: operator = (rptr < GuiBoundsComposition >  value)
62      {
63           throw   0 ;
64      }
65      
66       void  GuiBoundsComposition::SetBounds(Rect value)
67      {
68           throw   0 ;
69      }
70      
71      Margin GuiBoundsComposition::GetAlignmentToParent()
72      {
73           throw   0 ;
74      }
75       void  GuiBoundsComposition::SetAlignmentToParent(Margin value)
76      {
77           throw   0 ;
78      }
79      
80      GuiGraphicsEvent_of_GuiEventArgs GuiBoundsComposition::on_BoundsChanged()
81      {
82           throw   0 ;
83      }

    dll接口的部分生成比较简单,因为类似int这样的类型可以直接使用,而不像反射一样还得给一个对象来告诉你这个是int。

    之所要这两部分,是因为GacUI不仅允许用户直接操作某个控件,也需要同时允许界面使用XML描述,或者以后对脚本的支持。C++访问控件不需要反射,而XML和脚本则需要。XML描述界面是很重要的,因为这不仅可以用来支持皮肤、资源等高级抽象,还可以围绕XML开发一个跟Blend Expression(当然不可能有那么高级= =b)的GUI编辑器。

    接下来会继续给这些函数生成实现。这部分完成之后,GacUI就真正可以通过dll的方法来运行了。一旦把功能都坐进了dll,那么实现类似visual studio那样的可以把界面插件分散在各个dll里面的编辑器框架,也消除了技术上的困难。

你可能感兴趣的:(GacUI从pdb生成反射和dll接口首战告捷)