【问题标题】:How can I get List of objects with Generic type in Delphi如何在 Delphi 中获取具有通用类型的对象列表
【发布时间】:2015-07-22 12:56:36
【问题描述】:

我有几个类如下:

Type
  TSystemBaseEntity = class(TPersistent)
  private 
    FID: integer;
  public
    property ID: integer read FID write FID;
  end;

  TProcessHeaderEntity = class(TSystemBaseEntity)
  private
    FHeaderDate: TDateTime;
  public
     property HeaderDate: TDateTime read FHeaderDate write FHeaderDate;
  end;

  TInvoiceHeaderEntity = class(TProcessHeaderEntity)
  private 
    FCustomerId: integer;
  public
    property CustomerId: integer read FCustomerId write FCustomerId;
  end;


  TRequestHeaderEntity = class(TProcessHeaderEntity)
  private 
    FWarehouseId: integer;
  public
    property WarehouseId: integer read FWarehouseId write FWarehouseId;
  end;


  TDataList = class(TPersistent)
  private
    FValues: TObjectList<TSystemBaseEntity>;
  protected
    function SetCaption: string; virtual;
  public
    procedure Execute; virtual; abstract;
    property Values: TObjectList<TSystemBaseEntity> read FValues;
  end;

  TInvoice = class(TDataList)
  public
    procedure Execute; override;
  end;

如何通过 Values 属性获取具有从 TSystemBaseEntity 继承的泛型类型的对象列表?

例如,发票列表 (TInvoiceHeaderEntity) 或请求列表 (TRequestHeaderEntity) 以及对其属性的访问权限。

【问题讨论】:

  • 没有内置的方法可以按内容类型过滤列表,如果这就是您所要求的。如果这不是您要问的,那么我不确定您的障碍是什么。
  • 如何获取列表?从哪里得到?你的意见是什么?
  • @DavidHeffernan,我需要有一个类型列表,通过传递一个类型(例如 TInvoiceHeaderEntity ) TDataList 会给我一个列表
  • 请再次阅读我的评论并尝试解决我提出的问题。

标签: delphi generics delphi-2010


【解决方案1】:

如果您想要一个包含 TSystemBaseEntity 的一个特定子类的 TDataList,请将 TDataList 定义为泛型类,并带有 type constraint

这被定义为

  TDataList<T:TSystemBaseEntity> = class(TPersistent)
  private
    FValues: TObjectList<T>;
  protected
    function SetCaption: string; virtual;
  public
    procedure Execute; virtual; abstract;
    property Values: TObjectList<T> read FValues;
  end;

并用作

  TInvoice = class(TDataList<TInvoiceHeaderEntity>)
  public
    procedure Execute; override;
  end;

procedure TInvoice.Execute
var
  InvoiceHeader: TInvoiceHeaderEntity;
begin
  for InvoiceHeader in Values do
    ...
end;

如果您想要一种类型的 TDataList,其成员为 TObjectList&lt;TSystemBaseEntity&gt;,则不能将其用作 TObjectList&lt;TInvoiceHeaderEntity&gt; 等。请查看 Wikipedia 的介绍,但还要考虑允许以下内容在这样的计划下:

procedure DoBadThingsWithGenerics(aDataList: TDataList);
var
  myInvoices: TObjectList<TInvoiceHeaderEntity>
  myRequests: TObjectList<TRequestHeaderEntity>
  Request: TRequestHeaderEntity;
begin
  myInvoices := aDataList.Values<TInvoiceHeaderEntity>;
  myRequests := aDataList.Values<TRequestHeaderEntity>;

  // Some code ...

  myInvoices.Add( TInvoiceHeaderEntity.Create );

  // Some more code...

  for Request in myRequests do
    // Oops, we have a TInvoiceHeaderEntity pretending to be a TRequestHeaderEntity
end;

你可以在这里做的是有一个过程,它接受一个新的后代类型列表,过滤值列表中适当类型的元素并将它们添加到新列表中。

procedure TDataList.FilterByType<S:TSystemBaseEntity> ( intoList: TObjectList<S> );
var
  Value: TSystemBaseEntity;
begin
  for Value in Values do
    if Value is S then
      intoList.Add( Value as S );
end;

【讨论】:

  • 我希望 Values 是一个泛型类并将类型传递给它,然后将 Values 作为传递的类型。
  • 您是否要求具有通用属性值的非通用 TDataList?类似于“属性值:TObjectList”?德尔福不支持。上面的 TInvoice 将允许您使用在 TInvoiceHeaderEntity 中声明的成员及其 Values 属性的元素
  • 你能澄清我的答案的哪一部分是你所追求的吗?
  • 我使用了第一部分:TInvoice = class(TDataList)
猜你喜欢
  • 2019-07-31
  • 2011-04-12
  • 2021-07-12
  • 2011-06-12
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 2023-01-26
相关资源
最近更新 更多