Delphi FireMonkey中如何访问其他单元实现部分的TDayItem类型?
我正在Delphi FireMonkey中继承FMX.Calendar.Style单元,扩展TCalendar组件的拖拽选择多日(日期范围)功能,已有初步可行原型。但在另一个单元继承TStyledCalendar类时,提取选中日期需要转换为TDayItem类型,而该类型定义在FMX.Calendar.Style的实现部分,无法在其他单元访问。请问有没有办法访问该类型?
附相关代码片段:
unit FMX.Calendar.Style; interface {$SCOPEDENUMS ON} uses System.Classes, .., .. type { TStyledCalendar } TStyledCalendar = class(TStyledPresentation) public const CountOfVisibleDays = 6 * 7; .. .. .. end; implementation uses System.SysUtils, .. .. type TDayItem = class(TListBoxItem) private FDate: TDateTime; public property Date: TDateTime read FDate write FDate; end; .. ..
方法1:利用RTTI读取日期属性(推荐,无需修改原单元)
因为TDayItem本质是TListBoxItem,且有公开的Date属性,你可以通过RTTI在外部单元获取该属性值,不用直接依赖TDayItem类型:
uses System.Rtti; function GetDayItemDate(const AItem: TListBoxItem): TDateTime; var Context: TRttiContext; Prop: TRttiProperty; begin Result := 0; if not Assigned(AItem) then Exit; Context := TRttiContext.Create; try Prop := Context.GetType(AItem.ClassType).GetProperty('Date'); if Assigned(Prop) then Result := Prop.GetValue(AItem).AsType<TDateTime>; finally Context.Free; end; end;
使用时,直接把选中的TListBoxItem传入这个函数就能拿到日期,完全不用管TDayItem的定义位置。
方法2:复制TDayItem定义到你的单元(需保持结构一致)
如果确定TDayItem的结构不会随Delphi版本变更,你可以在自己的单元里复制一份完全相同的类定义:
type TDayItem = class(TListBoxItem) private FDate: TDateTime; public property Date: TDateTime read FDate write FDate; end;
之后就可以把TListBoxItem强制转换为这个本地定义的TDayItem来访问Date属性。但要注意:如果后续FMX.Calendar.Style里的TDayItem结构发生变化(比如新增字段或修改属性),你的代码可能会出现兼容性问题。
方法3:修改原FMX.Calendar.Style单元(不推荐,除非你能维护修改)
把TDayItem的定义从implementation段移到interface段,这样外部单元就能直接引用。但这种方法的弊端很明显:每次Delphi升级或组件库更新时,你的修改会被覆盖,需要重新手动调整,维护成本高。
方法4:在FMX.Calendar.Style单元中添加类助手(需修改原单元)
如果不想把TDayItem移到接口段,可以在FMX.Calendar.Style的interface段添加一个类助手,提供获取日期的方法:
// 在FMX.Calendar.Style的interface段添加 type TListBoxItemHelper = class helper for TListBoxItem public function GetDayDate: TDateTime; end; // 在FMX.Calendar.Style的implementation段实现 function TListBoxItemHelper.GetDayDate: TDateTime; begin if Self is TDayItem then Result := TDayItem(Self).Date else Result := 0; end;
这样外部单元只要引用FMX.Calendar.Style,就能通过TListBoxItem.GetDayDate方法获取日期。不过同样存在方法3的维护问题。
内容的提问来源于stack exchange,提问作者Edward

