日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DataSnap 2009 系列之二 (方法篇)

發布時間:2025/4/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DataSnap 2009 系列之二 (方法篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在過去客戶端要調用遠程服務器的方法需要通過在TLB里添加接口并且在服務器對象中實現

在DataSnap 2009中調用遠程服務器的方法是基于delphi的RTTI機制的

想要一個類允許被遠程調用需要做以下兩點

1.把該類和DSServerClass連接在一起

procedure TMainForm.DSServerClassGetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
begin
PersistentClass :
= TSM;
end;

DSServerClass的OnGetClass就是用于完成此任務的

注意:DSServerClass必須設置要導出的類 否則會出現SOnGetClassNotSet的異常信息

2.該類必須使用$MethodInfo編譯指令生成詳細的RTTI信息

{$MethodInfo ON}
TDSServerModule
= class(TProviderDataModule)
end;
{$MethodInfo OFF}

我們查看TDSServerModule的定義發現已經完成了該步驟

所以我們使用向導添加的ServerModule 不需要再手動添加$MethodInfo開關

同樣我們也可以不用繼承自TDSServerModule來實現我們的ServerClass

只要從TPersistent繼承一個類 并且用{$MethodInfo ON}和{$MethodInfo OFF}包圍就可以輸出成員函數到客戶端

注意:要輸出的成員函數必須聲明為public

客戶端調用可以使用兩種方法

1.使用SqlServerMethod組件

通過設置其ServerMethodName屬性來進行遠程調用 使用Params屬性來傳遞參數和結果值

2.使用本地代理類

選中SQLConnection組件,在右鍵菜單中單擊Generate Datasnap client classe 生成代理類單元。

下面我們通過一個簡單的DEMO來展示DataSnap 2009的遠程方法調用

我們在服務端定義了4個輸出的成員函數

TSM = class(TDSServerModule)
public
function Hello(Message: String): String;
function VariantMethod(Value: OleVariant): OleVariant;
function StreamMethod: TStream;
function VarOutMethod(out OutParam: OleVariant; var VarParam: OleVariant): string;
end;


由于在DataSnap內部是使用TDBXValue來管理參數列表的

所以使用string等delphi語言自帶的類型將會進行相應的映射

使用TDBXValue也是效率最高的

以下是可以作為參數使用的TDBXValue列表

TDBXWideStringValue
TDBXAnsiStringValue
TDBXInt16Value
TDBXInt32Value
TDBXInt64Value
TDBXSingleValue
TDBXDoubleValue
TDBXBcdValue
TDBXTimeValue
TDBXDateValue
TDBXTimeStampValue
TDBXBooleanValue
TDBXReaderValue
TDBXStreamValue

我們分別使用SqlServerMethod和代理類完成對服務端Hello方法的調用

SqlServerMethod.ServerMethodName := 'TSM.Hello';
SqlServerMethod.Params[
0].AsString := Name.Text;
SqlServerMethod.ExecuteMethod;
Memo.Lines.Add(
'Use SqlServerMethod: ' + SqlServerMethod.Params[1].AsString);


這里參數使用了索引值進行訪問 傳遞的順序是從左到右添加到Params列表 返回值是在列表的最后一個位置

同樣也可以使用ParamByName(參數名稱).Value的形式傳遞參數 返回值的名稱默認是'ReturnParameter'

使用代理類調用的方法和調用本地方法區別不大 因為遠程調用的具體過程已經被代理類封裝

可以看下代理類中生成的Hello方法

function TSMClient.Hello(Message: string): string;
begin
if FHelloCommand = nil then
begin
FHelloCommand :
= FDBXConnection.CreateCommand;
FHelloCommand.CommandType :
= TDBXCommandTypes.DSServerMethod;
FHelloCommand.Text :
= 'TSM.Hello';
FHelloCommand.Prepare;
end;
FHelloCommand.Parameters[
0].Value.SetWideString(Message);
FHelloCommand.ExecuteUpdate;
Result :
= FHelloCommand.Parameters[1].Value.GetWideString;
end;


我們看到代理類使用了比SqlServerMethod更低級的DBXCommand進行了封裝 以更友好的方式給我們使用

with TSMClient.Create(SQLConnection.DBXConnection) do
begin
Memo.Lines.Add(
'Use Proxy: ' + Hello(Name.Text));
Free;
end;

下面我們用TStream返回一個結構體并且在客戶端讀出

服務端部分

TName = packed record
FirstName:
array[0..99] of Char;
LastName:
array[0..99] of Char;
end;

function TSM.StreamMethod: TStream;
var
Name: TName;
begin
Name.FirstName :
= '愛新覺羅';
Name.LastName :
= '玄燁';
Result :
= TMemoryStream.Create;
Result.Seek(
0, soFromBeginning);
Result.Write(Name, SizeOf(TName));
Result.Seek(
0, soFromBeginning); //返回到客戶端的數據是從position開始的
end;

注意:寫完數據以后需要定位到頭部 否則客戶端得到的數據長度為0


客戶端部分

procedure TMainForm.StreamTestClick(Sender: TObject);
var
Name: TName;
begin
if SQLConnection.Connected then
begin
with TSMClient.Create(SQLConnection.DBXConnection) do
begin
StreamMethod.ReadBuffer(Name, SizeOf(TName));
Memo.Lines.Add(Format(
'(StreamMethod)FirstName: %s LastName: %s',[Name.FirstName, Name.LastName]));
Free;
end;
end;
end;

最后一個函數演示了使用var和out關鍵字來返回參數

以下是可以使用這兩個關鍵字的標量值類型

boolean
SmallInt
Integer
Int64
Single
Double
AnsiString
String
TDBXTime
TDBXDate

再加上其他的參數類型

TStream
TDataSet
TParams
TDBXReader
TDBXConnection

但是在實際測試過程中發現在使用string類型做out和var的參數時 無法使用

跟蹤發現源碼中ansistring和string的相關代碼已經被注釋掉 估計是有BUG存在所以不支持 以后應該可以修復

以下摘自DSReflect單元的procedure TDSMethodValues.AssignParameterValues(Parameters: TDBXParameterArray);

// TDBXDataTypes.AnsiStringType:
// begin
// s := Value.GetAnsiString;
// GetMem(p, SizeOf(Pointer));
// UniqueString(s);
// PPointer(p)^ := Pointer(s);
// FMethodValues[i] := MakeRefVar(varString, p);
// end;
// TDBXDataTypes.BytesType:
// begin
// SetLength(bytes, value.GetValueSize);
// Value.GetBytes(0, bytes, 0, Length(Bytes));
// GetMem(p, Length(bytes));
// Move(bytes[0], p^, Length(bytes));
// FMethodValues[i] := MakeRefVar(varByte or varArray, p);
// end;
// TDBXDataTypes.WideStringType:
// begin
// w := Value.GetWideString;
// GetMem(p, SizeOf(Pointer));
// UniqueString(w);
// PPointer(p)^ := Pointer(w);
// FMethodValues[i] := MakeRefVar(varUString, p);
// end;

貼上效果圖


附上DEMO源碼 DataSnapDemo_2.rar

轉載于:https://www.cnblogs.com/MaxWoods/archive/2011/09/23/2187839.html

總結

以上是生活随笔為你收集整理的DataSnap 2009 系列之二 (方法篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。