Using COM to Transfer Any Type of Data
unit TransComponent;
{本工具供Com/DCom间传递组件(从TComponent继承的所有对象)
调用 VariantToComponent 时会出现 "Class <TClassName> not Found "提示 多次 ,
在调用单元的initialization段加以下语句:
RegisterClass(<ClassName>),如
RegisterClass(TClientDataSet);
RegisterClass(TStringField);
VariantToComponent 的参数 Component 必须声明为TComponent,然后使用强制类型转换使用它
如:TClientDataSet(Component)
}
interface
uses SysUtils,Classes;
procedure ComponentToVariant(const Component:TComponent;out vData:OleVariant);
procedure VariantToComponent(out Component:TComponent; vData:OleVariant);
implementation
procedure UnloadVariantArray(
var VData: OleVariant; PData: Pointer;
NumBytes: Integer);
var
PVData: PByteArray;
begin
{ Lock the variant array, copy the data to the array, and
unlock the variant array. }
PVData := VarArrayLock(VData);
try
{ Move the data in memory that PVData points to (the
variant array data), to the location in memory that
PData points to (the integer array). }
Move(PVData^, PData^, NumBytes);
finally
VarArrayUnlock(VData);
end; // try
end;
procedure LoadVariantArray(PData: Pointer;
NumBytes: Integer; var VData: OleVariant);
var
PVData: PByteArray;
begin
{ Create the variant array of bytes. Set the upper bound
to the size of the array, minus one, because the array
is zero-based. }
VData := VarArrayCreate([0, NumBytes - 1], varByte);
{ Lock the variant array for faster access. Then copy the
array to the variant array, and unlock the variant
array. }
PVData := VarArrayLock(Vdata);
try
{ Move the bytes at the location in memory that PData
points to into the location in memory that PVData
points to. PData points to the integer array and
PVData points to the variant array of bytes. }
Move(PData^, PVData^, NumBytes);
finally
VarArrayUnlock(VData);
end; // try
end ;
procedure ComponentToVariant(const Component:TComponent;out vData:OleVariant);
var
CompBuffer:TByteArray;
pCompBuffer:pointer;
begin
with TMemoryStream.Create do
try
WriteComponent(Component);
Seek(0, soFromBeginning);
ReadBuffer(CompBuffer,Size);
LoadVariantArray(@CompBuffer,Size,vData);
finally
free;
end;
end;
procedure VariantToComponent(out Component:TComponent; vData:OleVariant);
var
CompBuffer:TByteArray;
pCompBuffer:pointer;
begin
with TMemoryStream.Create do
try
UnLoadVariantArray(vData,@CompBuffer,VarArrayHighBound(vData,1)+1);
WriteBuffer(CompBuffer,VarArrayHighBound(vData,1)+1);
Seek(0, soFromBeginning);
Component:=ReadComponent(nil);
//-the Component is AutoCreated
finally
free;
end;
end;
end.
通过Com接口一般只能传递Microsoft为Com定义的有限参数类型,Delphi封装了
TClientDataSet.data使之可以按Variant类型传递。我写的单元是把所有继承自
TComponent的对象转换成OleVariant,这样组件的定义和数据就可以作为Com参数传递。
有何用?
举个例子,基于多层结构的客户界面如果需要作微调,必须重新发放客户界面代码。
如果我把客户界面资源存成资源文件放在服务器,客户程序通过DCom调用远程载入
客户界面,就不须每次版本更新时重新部署客户程序。当然,考虑到运行效率,我
还没有把这个技术用于工程中。
在基于Com的模块化编程中,可以用语Com间复杂参数的传递,但这样设计的Com是不能
跨语言调用的。
事实上,如果单纯传递TComponent,可以使用
TStream.ReadComponent中例子的ComponentToString&StringToComponent两个
函数互相转换(把Bin/text格式的dfm互转),没有必要用到我那个苯函数。
上述函数调用ObjectBinaryToText&ObjectTextToBinary
处理TPersistent可能可以使用它们解决。
vinson_zeng感兴趣的话花点时间作出来给大家共享如何?