亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

用DELPHI的RTTI實現對象的XML持久化

2019-11-18 18:04:02
字體:
來源:轉載
供稿:網友
去年我花了很多時間嘗試用DELPHI進行基于xml的WEB應用開發。起初的設想是很美好的,但結果做出來的東西很簡陋。一部分原因就在于XML到Object之間的數據綁定實現太麻煩(另一部分是因為對XSLT不熟,學習它花了很多時間)。

    之前我一直是用DELPHI提供的XML Data binding來做的,基本做法是:先用工具(如XMLSPY)做好一個XML Schema(XSD),然后用XML Data binding生成DELPHI的接口和類。當然,一旦生成好就很方便了,在程序里我只要操作這個接口就好了,其中各個Field都會被變成屬性,并且類型也都如我在XSD中的定義。但問題在于程序在開發過程中,總是會有一些變化的,在這種情況下,我就不得不同時開著XMLSPY修改XSD,然后重新用 XML Data binding的Wizard跑一遍,非常的麻煩。

    所以當我想到數據集的對象化后,立即想到也可以用RTTI來實現Object的XML持久化--其實DELPHI6開始的SOAP實現就是用RTTI來實現Object到SOAP數據(就是XML)的轉換的。顯然我已經是非常的后知后覺了,當我在《強大的DELPHI RTTI--兼談需要了解多種開發語言》一文中說到我的打算時,朋友Lex CHow回復我說他在大約一年前就做過了這方面的工作,我當即跟他要來了他的源碼。lexlib是他寫的是一個有很多功能的庫,看上去結構有點像.net 的基本類庫(當然沒那么大^O^),Object的XML持久化只是其中的很小的一部分。因為我只需要這一部分,就沒必要用這整個一個庫這么麻煩,于是參考了lexlib并結合我在《用DELPHI的RTTI實現數據集的簡單對象化》中已經實現的部分,做了一個簡單的實現:

    TMXMLPersistent = class(TObject)    public        class PRocedure LoadObjFromXML( aNode : IXMLNode; aObj : TPersistent );        class Procedure SaveObjToXML(   aNode : IXMLNode; aObj : TPersistent );    end;const    DefaultFilter : TTypeKinds = [tkInteger, tkChar, tkEnumeration,        tkFloat, tkString, tkSet, tkWChar, tkLString, tkWString, tkInt64];{ TMXMLPersistent }class procedure TMXMLPersistent.LoadObjFromXML(aNode: IXMLNode;  aObj: TPersistent);Var    i : Integer;    pList : TMPropList;    pInfo : PPropInfo;    tmpObj: TObject;begin    If ( aObj Is TMDataSetProxy ) Then        ( aObj As TMDataSetProxy ).LoadFromXML( aNode )    Else    Begin        pList := TMPropList.Create( aObj );        Try            For i := 0 To pList.PropCount - 1 Do            Begin                pInfo := pList.Props[i];                If ( pInfo^.PropType^.Kind = tkClass ) Then                Begin                    tmpObj := TObject( Integer( GetPropValue( aObj, pInfo^.Name ) ) );                    If ( Assigned( tmpObj ) AND ( tmpObj Is TPersistent ) ) Then                        LoadObjFromXML( aNode.ChildNodes[WideString(pInfo^.Name)],                            tmpObj As TPersistent );                End                Else If ( pInfo^.PropType^.Kind In DefaultFilter ) Then                    SetPropValue( aObj, pInfo^.Name,                        String( aNode.ChildNodes[WideString( pInfo^.Name )].Text ) );            End;        Finally            pList.Free;        End;    End;end;class procedure TMXMLPersistent.SaveObjToXML(aNode: IXMLNode;  aObj: TPersistent);Var    i : Integer;    pList : TMPropList;    pInfo : PPropInfo;    tmpObj: TObject;begin    If ( aObj Is TMDataSetProxy ) Then        ( aObj As TMDataSetProxy ).SaveToXML( aNode )    Else    Begin        pList := TMPropList.Create( aObj );        Try            For i := 0 To pList.PropCount - 1 Do            Begin                pInfo := pList.Props[i];                If ( pInfo^.PropType^.Kind = tkClass ) Then                Begin                    tmpObj := TObject( Integer( GetPropValue( aObj, pInfo^.Name ) ) );                    If ( Assigned( tmpObj ) AND ( tmpObj Is TPersistent ) ) Then                        SaveObjToXML( aNode.AddChild( WideString( pInfo^.Name ) ),                            tmpObj As TPersistent );                End                Else If ( pInfo^.PropType^.Kind In DefaultFilter ) Then                    aNode.AddChild( WideString( pInfo^.Name ) ).Text :=                        GetPropValue( aObj, pInfo^.Name );            End;        Finally            pList.Free;        End;    End;end;

    這個實現應該說是很簡單的。主要是三個部分(Load和Save的結構是相似的):

    一是對TMDataSetProxy作特別處理,委托給這個類自己去處理它的實現,因為它與一般的類不同,需要通過ForEach遍歷全部記錄,這其實就是同時實現數據集的XML持久化。

    二是對Class作遞歸處理,當然只支持從TPersistent派生的class。

    三是一般的Field簡單地轉成String保存,其中借鑒了lexlib的Filter,只處理那些能簡單地轉成String的數據類型,過濾掉那些可能造成轉換出錯的類型。

    上面的代碼中用到的TMPropList見《用DELPHI的RTTI實現數據集的簡單對象化》中的實現。

    下面是用TMDataSetProxy實現的數據集的XML持久化。免去了需要通過TClientDataSet進行的麻煩,并且采用的是用Node記錄字段的方式,.net也是采用這樣的方式,與TClientDataSet所用的用Attribute記錄字段的方式不同。雖然這樣生成的 XML文件將會略大一些,但是好處也是顯而易見的,特別是我是準備用在Web應用中的,用Node方式記錄的XML,在用XSLT時會方便很多。

procedure TMDataSetProxy.LoadFromXML(aNode: IXMLNode);Var    i, j : Integer;    pInfo : PPropInfo;    pRow  : IXMLNode;begin    For j := 0 To aNode.ChildNodes.Count - 1 Do    Begin        FDataSet.Append;        pRow := aNode.ChildNodes[j];        For i := 0 To FPropList.PropCount - 1 Do        Begin            pInfo := FPropList.Props[i];            If ( pInfo^.PropType^.Kind In DefaultFilter ) Then                SetVariant( i,                    String( pRow.ChildNodes[WideString( pInfo^.Name )].Text ) );        End;        EndEdit;    End;    FDataSet.First;end;procedure TMDataSetProxy.SaveToXML(aNode: IXMLNode);Var    i : Integer;    pInfo : PPropInfo;    pRow  : IXMLNode;begin    While ForEach Do    Begin        pRow := aNode.AddChild( 'Row' );        For i := 0 To FPropList.PropCount - 1 Do        Begin            pInfo := FPropList.Props[i];            If ( pInfo^.PropType^.Kind In DefaultFilter ) Then                pRow.AddChild( WideString( pInfo^.Name ) ).Text                    := GetVariant( i );        End;    End;end;

    下面是一個簡單的DEMO,其中包括了對數據集的XML持久化。注意Load的時候Employee成員連接的是ADODataSet2,它連接到一個包含了這幾個字段的表,各字段類型與Employee表相同,但內容為空,并且去掉了EmployeeID的Identity。Load完成后,Employee表中這幾個字段的內容將被復制到此表中。

    TDemoCompany = class( TPersistent )    private        FEmployee : TDSPEmployee;        FCompany  : String;        FCode     : Integer;    published        property Employee : TDSPEmployee Read FEmployee Write FEmployee;        property Company  : String       Read FCompany  Write FCompany;        Property Code     : Integer      Read FCode     Write FCode;    End;procedure TForm1.SaveClick(Sender: TObject);Var    demo : TDemoCompany;begin    demo := TDemoCompany.Create;    demo.Employee := TDSPEmployee.Create( ADODataSet1 );    demo.Company  := 'Demo company';    demo.Code     := 987654;    Try        XMLDocument1.Active := true;        TMXMLPersistent.SaveObjToXML( XMLDocument1.AddChild( 'Demo' ), demo );        XMLDocument1.SaveToFile( 'temp.xml' );        XMLDocument1.Active := false;    Finally        demo.Employee.Free;        demo.Employee := Nil;        demo.Free;    End;end;procedure TForm1.LoadClick(Sender: TObject);Var    demo : TDemoCompany;begin    demo := TDemoCompany.Create;    demo.Employee := TDSPEmployee.Create( ADODataSet2 );    Try        XMLDocument1.Active := true;        XMLDocument1.LoadFromFile( 'temp.xml' );        TMXMLPersistent.LoadObjFromXML( XMLDocument1.ChildNodes.Last, demo );        XMLDocument1.Active := false;        Edit1.Text := demo.Company;        Edit2.Text := IntToStr( demo.Code );        While ( demo.Employee.ForEach ) Do        With ListView1.Items.Add Do        Begin            Caption := IntToStr( demo.Employee.EmployeeID );            SubItems.Add( demo.Employee.FirstName );            SubItems.Add( demo.Employee.LastName );            SubItems.Add( FormatDateTime( 'yyyy-mm-dd', demo.Employee.BirthDate ) );        End;    Finally        demo.Employee.Free;        demo.Employee := Nil;        demo.Free;    End;end;

    終于可以告別那個麻煩的XML Data binding了,并且以后也不用寫XSD了--雖然有好用的工具,但能省點事終歸是好的。


上一篇:Delphi中實現漢字拼音聲母查詢

下一篇:用DELPHI的RTTI實現數據集的簡單對象化

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久亚洲精品| 日韩欧美中文字幕在线播放| 亚洲免费电影在线观看| 日韩精品视频免费| 亚洲视频777| 精品久久久在线观看| 国产日韩av在线| 日韩精品福利网站| 国产精品日韩欧美大师| 国产区亚洲区欧美区| 色综合久综合久久综合久鬼88| 精品亚洲永久免费精品| 亚洲成人a**站| 国内揄拍国内精品少妇国语| 北条麻妃久久精品| 欧美日韩国产精品一区二区不卡中文| 国内免费久久久久久久久久久| 日韩精品在线影院| 亚洲免费人成在线视频观看| y97精品国产97久久久久久| 久久国产精品久久国产精品| 日韩在线观看免费全集电视剧网站| 亚洲国产天堂久久国产91| 国产精品久久久久免费a∨| 久久噜噜噜精品国产亚洲综合| 狠狠躁夜夜躁久久躁别揉| 最近2019年日本中文免费字幕| 欧美激情中文字幕在线| 欧美电影免费观看| 一本色道久久综合狠狠躁篇怎么玩| 欧美理论片在线观看| 88国产精品欧美一区二区三区| 日韩a**站在线观看| 亚洲国产成人精品女人久久久| 国产成人精品电影久久久| 视频在线观看99| 久久伊人精品天天| 成人国产在线视频| 精品国产区一区二区三区在线观看| 欧美激情一区二区三区久久久| 欧美精品激情blacked18| 亚洲人成在线播放| 欧美精品videosex牲欧美| 91免费欧美精品| 欧美日韩精品中文字幕| 国模视频一区二区三区| 欧美最近摘花xxxx摘花| 国产精品国产三级国产aⅴ9色| 久久97久久97精品免视看| 伊人久久久久久久久久| 亚洲国产成人精品一区二区| 91精品国产综合久久香蕉最新版| 91老司机精品视频| 日韩欧美亚洲范冰冰与中字| 国产999在线| 日韩在线视频导航| 日韩成人av一区| 免费91麻豆精品国产自产在线观看| 亚洲国产成人久久| 亚洲2020天天堂在线观看| 亚洲aa在线观看| 欧美一级淫片aaaaaaa视频| 欧美日韩裸体免费视频| 91麻豆桃色免费看| 亚洲一区美女视频在线观看免费| 亚洲一区二区三区久久| 国产精品视频久久| 中文字幕日本欧美| 国产精品美女久久久免费| 久久五月情影视| 久久夜色精品亚洲噜噜国产mv| 亚洲国产欧美一区二区三区同亚洲| 亚洲专区中文字幕| 亚洲性线免费观看视频成熟| 在线午夜精品自拍| 精品久久久久久亚洲国产300| 中文精品99久久国产香蕉| 欧美极品在线视频| 国产日韩精品入口| 日韩亚洲在线观看| 亚洲成人久久久久| 欧美老女人www| 欧美成人激情在线| 国内精品久久久久伊人av| 国产精品直播网红| 日韩免费观看在线观看| 久久免费观看视频| 成人444kkkk在线观看| 久久久亚洲成人| 久久在线观看视频| 日韩一区视频在线| 久久久国产精彩视频美女艺术照福利| 国产精品v日韩精品| 欧美老少做受xxxx高潮| 亚洲热线99精品视频| 性欧美暴力猛交69hd| 91免费的视频在线播放| 综合国产在线视频| 性色av一区二区三区红粉影视| 成人精品视频99在线观看免费| 久色乳综合思思在线视频| 欧美日韩国产麻豆| 成人欧美在线视频| 国产成人精品综合久久久| 色偷偷888欧美精品久久久| 欧美综合在线第二页| 免费97视频在线精品国自产拍| 亚洲国产91色在线| 欧美性视频在线| 久久久久日韩精品久久久男男| 久久久国产精品视频| 国产日韩中文字幕在线| 欧美成人性生活| 91精品视频一区| 欧美大尺度电影在线观看| 精品久久中文字幕久久av| 尤物yw午夜国产精品视频| 欧美日韩国产色视频| 91色视频在线观看| 亚洲一区二区三区成人在线视频精品| 亚洲欧美精品一区| 国产精品久在线观看| 欧美精品电影免费在线观看| 亚洲欧洲自拍偷拍| 国产成人97精品免费看片| 97国产精品免费视频| 97精品久久久| 国产一区二区日韩精品欧美精品| 国产精品狼人色视频一区| 亚洲图片欧美午夜| 精品在线小视频| 国产亚洲精品久久久久久| 欧美在线一区二区视频| 中文字幕欧美国内| 久久精品91久久久久久再现| 97碰在线观看| 国产精品白丝av嫩草影院| 亚洲精品电影网| 欧美综合一区第一页| 蜜臀久久99精品久久久久久宅男| 黑人精品xxx一区一二区| 91tv亚洲精品香蕉国产一区7ujn| 国产精品夜色7777狼人| 1769国内精品视频在线播放| 成人精品在线视频| 国产精品看片资源| 97视频在线观看播放| 成人性生交xxxxx网站| 91黑丝在线观看| 亚洲女性裸体视频| 国产一区二区欧美日韩| 午夜精品免费视频| 亚洲成人av片在线观看| 色视频www在线播放国产成人| 亚洲精品一区二区久| 91在线精品播放| 青草成人免费视频| 亚洲美腿欧美激情另类| 日本免费一区二区三区视频观看| 欧美高跟鞋交xxxxhd| 国产精品久久网| 国产精品久久久久久搜索| 国产亚洲精品美女久久久久| 久热精品视频在线观看|