【发布时间】:2015-12-29 12:22:34
【问题描述】:
我想复制通用对象,但它的类型只能在运行时通过“类”构造获得,因为源对象类型可能不同(TItem 或 TSpecificItem 等):
type
TItem = class
//...
procedure Assign(Source: TItem);virtual; abstract; //edit
end;
TSpecificItem = class(TItem)
//...
end;
TEvenMoreSpecificItem = class(TSpecificItem)
//...
end;
TItemClass = class of TItem;
TItemContainer = class
FItems: TObjectList<TItem>; //edit
procedure Assign(Source: TObject); //edit
function GetItem(Index: Integer): TItem; inline; //edit
procedure SetItem(Index: Integer; Item: TItem); inline; //edit
function Count: Integer; //edit;
function ItemClass: TItemClass; virtual; abstract;
property Items[Index: Integer]: TItem read GetItem write SetItem; //edit
end;
TItemContainer<T: TItem> = class(TItemContainer)
//...
function GetItem(Index: Integer): T; inline; //edit
procedure SetItem(Index: Integer; Item: T); inline; //edit
function ItemClass: TItemClass; override;
property Items[Index: Integer]: T read GetItem write SetItem; default; //edit
end;
//start of edit
function TItemContainer.Count: Integer;
begin
Result := FItems.Count;
end;
function TItemContainer.GetItem(Index: Integer): TItem;
begin
Result := FItems[Index];
end;
procedure TItemContainer.SetItem(Index: Integer; Item: TItem);
begin
FItems[Index].Assign(Item);
end;
procedure TItemContainer.Assign(Source: TObject);
var
I: Integer;
Item: TItem;
Cls: TClass;
begin
if Source is TItemContainer then
begin
FItems.Clear;
for I := 0 to TItemContainer(Source).Count - 1 do
begin
Item := TItemContainer(Source).Items[I];
Cls := Item.ClassType;
Item := TItemClass(Cls).Create;
Item.Assign(TItemContainer(Source).Items[I]);
FItems.Add(Item);
end;
end;
end;
function TItemContainer<T>.GetItem(Index: Integer): T;
begin
Result := T(inherited GetItem(Index));
end;
procedure TItemContainer<T>.SetItem(Index: Integer; Item: T);
begin
inherited SetItem(Index, Item);
end;
//end of edit
function TItemContainer<T>.ItemClass: TItemClass;
begin
Result := TItemClass(GetTypeData(PTypeInfo(TypeInfo(T)))^.ClassType);
end;
function CopyGenericObject(Source: TItemContainer): TItemContainer;
var
Cls: TItemClass;
begin
Cls := Source.ItemClass;
Result := TItemContainer<Cls>.Create; // compiler reports error "incompatible types"
Result.Assign(Source);
end;
// edit:
procedure DoCopy;
var
Source: TItemContainer<TEvenMoreSpecificItem>;
Dest: TItemContainer;
begin
Source := TItemContainer<TEvenMoreSpecificItem>.Create; // for example
//add some items to Source
Dest := CopyGenericObject(Source);
//use the result somewhere
end;
我必须使用 Delphi XE。
我找到了 http://docwiki.embarcadero.com/RADStudio/XE6/en/Overview_of_Generics
动态实例化
不支持在运行时动态实例化。
这是我想做的吗?
【问题讨论】:
-
除了您的语法错误之外,您尝试的通常是不可能的。您可能没有在编译时实际实例化具体类型
TDCollection<Cls>。与其问如何解决问题,不如问如何解决问题。这样会带来有用的帮助。 -
语法已更正。谢谢你的回答就足够了。我可以用另一种方式解决我的问题,但我只是想知道这是否可行。
-
我所说的语法错误的意思是
Cls在运行时是未知的,并且必须是泛型实例化。您可以使用 RTTI 创建实例,但必须实例化类型。 -
我之所以没有尝试向您展示如何操作,是因为我怀疑您的处理方式完全错误。很明显,你并不真正知道自己在做什么。您应该正视这一点并寻求帮助,为您的问题找到一个好的解决方案,而不是询问如何实施您的解决方案来解决我打赌是错误解决方案的问题。
-
@David 如果你愿意,让我们在我承认的答案下方进一步讨论。