얕은 복사와 깊이 복사(원형 모드)

Delphi의 VCL은 TPersistent에서 RTTI (RuntimeTypeInfo) 가 실행될 때 형식 정보를 지원합니다. 이것은 {$M+} 컴파일 명령을 통해 RTTI 기능을 제공합니다.M이 열리면 Delphi는 이 대상을 컴파일할 때 대상의 유형 정보를 실행 가능한 파일에 컴파일하여 실행할 때 대상의 속성과 방법 등 정보를 동적으로 얻을 수 있습니다.모든 VCL 시각화 구성 요소는 TPersistent에서 파생되기 때문에 구성 요소 정보를 dfm에 저장할 수도 있고 동적으로 불러올 수도 있습니다.
Delphi는 또한 허위 방법인 Assign,procedure Assign(Source:Tpersistent)을 정의했다.virtual;
이 방법은 바로 원본 대상의 속성을 목표 대상에 복제하는 데 쓰인다.기본적인 TPersistent 대상의 Assign 방법은 원본 대상의 Assign To 방법을 간단하게 호출해서 속성을 복제하는 것일 뿐이고 TPersistent의 Assign To 방법은 이상을 던져서 의미 있는 기능을 실현하지 못한다. 그러면 TPersistent에서 파생된 대상이 복제 기능을 제공하려면 TPersistent의 Assign이나 Assign To를 다시 불러와서 사용자 정의 복제 기능을 실현해야 한다.
 
클래스의 속성 목록 가져오기: TypInfo//rtti,contnrs,classes,sysutils를 참조하려면//{$M+}을(를) 엽니다.
procedure GetPropNames(AObject:TObject;var List:TStringList);
var
  I,Count:Integer;
  PropList:PPropList;//수조형 지침, 수조는 속성을 가리키는 기록형 정보의 지침형 수조이다.
  PKinds:TTypeKinds;//유형 정보의 집합
begin
  List.Clear;
  PKinds := [tkUnknow,tkInteger,tkChar,tkEnumeration,tkFloat,tkString,tkSet,tkClass,tkMethod,tkWChar,tkLString,tkWString,
tkVariant,tkArray,tkRecord,tkInterface,tkInt64,tkDynArray];
  Count := GetPropList(AObject.ClassInfo,pKinds,nil);
  GetMem(PropList,Count*SizeOf(Pointer));
  GetPropList(AObject.ClassInfo,PKinds,PropList);
  for I :=0 to count-1 do
  List.Add(PropList^[i].Name);
  FreeMem(PropList,Count*SizeOf(Pointer));
end;
 
procedure CloneObject(SrcObj,DesObj:TPersistent);
var
   NameList:TStringList;
  I:Integer;
  V:Variant;
begin
  if srcObj.ClassName<>DesObj.ClassName then
  raise Exception.Create('다른 유형의 객체, 복제할 수 없음');
  if (not Assigned(SrcObje)) or not (Assigned(DesObj)) then
  raise Exception.Create(객체는 비워둘 수 없음);
  NameList := TStringlist.create;
  GetPropNames(SrcObj,NameList);
 try
   for I:= 0 to Namelist.Count-1 do
  begin
      V:= GetPropValue(SrcObj,Namelist.Strings[I]);
     SetPropValue(DesObj,NameList.Strings[I],V);
finally
  Namelist.free;
end;
end;
여기서 GetPropName 함수는 Delphi의 TypeInfo 단원의 Rtti 함수를 호출하여 복제할 대상의 보호 수준이 Published인 속성 이름 문자열 목록을 가져옵니다.CloneObject는 대상의 속성 목록을 옮겨다니며 RTTI 함수GetPropValue를 사용하여 속성 이름으로 대상의 속성 값을 얻고 RTTI 함수의 SetPropValue를 통해 원본 대상 값에 값을 부여합니다.RTTI 함수는 Published 속성에만 유효하며 다른 보호 수준의 속성은 유효하지 않습니다.
위의 객체 복사 함수는 하위 객체인 TreeView와 같은 복합 객체에 대해 Tstrings가 유효하지 않으며 이러한 객체에 대해서도 수동으로 수행해야 합니다.
procedure TStrings.Assign(Source:TPersistent);
begin
  if Source is TStrings then
  begin
     Beginupdate;
    try
      Clear;
      FDefined:=TStrings(Source).FDefined;
      FNameValueSeparator := TStrings(Source).FNameValueSeparator;
      FQuoteChar := TStrings(Source).FQuoteChar;
      FDelimiter :=  TStrings(Source).FDelimiter;
      AddStrings(TStrings(Source));
    finally
      EndUpdate;
    end;
   Exit;
  end;
  inherited Assign(Source);
end;
 
delphi의 Assign 방법은 같은 유형의 대상의 복제를 실현할 수 있을 뿐만 아니라 서로 다른 대상 간의 복제도 실현할 수 있다. 가장 전형적인 것은 클립보드 TClipBoard이다. Windows의 클립보드는 텍스트, 비트맵, 도원 등 다양한 유형의 데이터를 저장할 수 있다. 클립보드의 비트맵 데이터를 대응하는 TBitmap이나 TMetafile 클래스에 직접 복제하기 위해VCL은 TClipboard 클래스의 AssignTo 메서드를 다시 로드하여 데이터를 다른 객체에 복사합니다.
 
 
procedure TClipboard.AssignTo(Dest: TPersistent);
begin
 if Dest is TPicture then
    AssignToPicture(TPicture(Dest))
 else if Dest is TBitmap then
    AssignToBitmap(TBitmap(Dest))
 else if Dest is TMetafile then
    AssignToMetafile(TMetafile(Dest))
 else inherited AssignTo(Dest);
end;
procedure TClipboard.AssignToBitmap(Dest: TBitmap);
var
 Data: THandle;
 Palette: HPALETTE;
begin
 Open;
 try
    Data := GetClipboardData(CF_BITMAP);
    Palette := GetClipboardData(CF_PALETTE);
    Dest.LoadFromClipboardFormat(CF_BITMAP, Data, Palette);
 finally
    Close;
 end;
end;
procedure TClipboard.AssignToMetafile(Dest: TMetafile);
var
//  
begin
//  
end;
procedure TClipboard.AssignToPicture(Dest: TPicture);
var
//
Begin
 //  
end;

좋은 웹페이지 즐겨찾기