- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在独自从事一个员工计时项目,该项目使用数据库来存储时间表条目。我在该项目中使用 Delphi Pro 10.2.3 Tokyo,并创建了一个包装类库,以方便使用普通类等数据集。例如,要访问 Employee 表中的 FirstName 字段,我可以写 LFirstName := FEmployee.FirstName;而不是 LFirstName := Dataset.FieldByName('FirstName').AsString;
我的一些类有大量依赖项(多达八个),我通过类的构造函数注入(inject)这些依赖项。我使用域对象来创建所需的接口(interface)并将它们注入(inject)到正在创建的类中。
一些被注入(inject)的接口(interface)本身也非常复杂,并且开始难以跟踪域对象中的所有内容。
注入(inject)的依赖项包括为计算字段提供查找值的其他表的包装器接口(interface)、指向创建类使用的创建对象的函数的指针或解析主/从关系的回调函数。这些关系是静态的,需要在构造函数中设置,以便在创建类时任何计算字段都将起作用。
是否有任何替代构造函数注入(inject)的方法可能会降低构造函数的复杂性,同时保持解耦类。这是我的一个模块中用于时间表条目的代码示例。
unit LevelPay.DbModel.TimesheetEntry;
interface
uses
Data.Db
, FireDAC.Comp.DataSet
, MyLib.Model.Interfaces
, LevelPay.Model.Types
, LevelPay.Model.Constants
, LevelPay.Model.Interfaces
, LevelPay.DbModel.AppModel
;
type
TDbCustomTimesheetEntry = class(
TDbAppModel<ITimesheetEntry>,
ITimesheetEntry
)
strict private
FCopyFunc: TCopyFunc<ITimesheetEntry>;
procedure ClearFilter;
procedure FilterEntries(const ADate: TDate);
strict protected
FTimesheet: ITimesheet;
FID: TField;
FEmployeeID: TField;
FPayPeriodEndDate: TField;
FFiscalYearEndDate: TField;
FFiscalYearStartDate: TField;
FRowNbr: TField;
FEntryTypeID: TField;
FDateIn: TField;
FTimein: TField;
FDateOut: TField;
FTimeOut: TField;
FCreatedBy: TField;
FCreatedTimestamp: TField;
FLastModifiedBy: TField;
FLastModifiedTimestamp: TField;
FNote: TField;
FClockable: TField;
FClockableHours: TField;
FDayOfWeek: TField;
FDifference: TField;
FEmployeeName: TField;
FEntryTypeCaption: TField;
FTimeElapsed: TField;
FDateIndex: TFDIndex;
FTimeScheduled: TField;
FScheduledTimeIn: TField;
FScheduledTimeOut: TField;
FWeekOf: TField;
function GetID: TIdentifier;
function GetModel: ITimesheetEntry; override;
function GetClockable: Boolean;
function GetClockableHours: THours;
function GetDateIn: TDate;
function GetDateOut: TDate;
function GetDifference: THours;
function GetEmployeeID: TIdentifier;
function GetEmployeeName: string;
function GetPayPeriodEndDate: TDate;
function GetFiscalYearStartDate: TDate;
function GetFiscalYearEndDate: TDate;
function GetEntryTypeID: TIdentifier;
function GetEntryTypeCaption: TCaption;
function GetPlaceholder: Boolean;
function GetRowNbr: TRowNbr;
function GetScheduledTimeIn: TTime;
function GetScheduledTimeOut: TTime;
function GetTimeElapsed: THours;
function GetTimein: TTime;
function GetTimeOut: TTime;
function GetTimeScheduled: THours;
function GetWeekOf: TDate;
function GetWeekDay: string;
function GetCreatedBy: TUserName;
function GetCreatedTimestamp: TDateTime;
function GetLastModifiedBy: TUserName;
function GetLastModifiedTimestamp: TDateTime;
function GetNote: AnsiString;
function GetEntry: ITimesheetEntry;
function GetTimesheet: ITimesheet;
function GetHasEntries: Boolean;
function Find(AModel: ITimesheetEntry): Boolean; override;
procedure DoUpdate(AModel: ITimesheetEntry); override;
procedure Load; virtual;
procedure CreateFields; override;
procedure CreateCalcFields; override;
procedure CreateIndexes; override;
procedure FormatFields; override;
procedure OnCalcFields(Dataset: TDataset); override;
procedure OnNewRecord(Dataset: TDataset); override;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ACreateFields: Boolean
); reintroduce;
property ID: TIdentifier read GetID;
property EmployeeID: TIdentifier read GetEmployeeID;
property PayPeriodEndDate: TDate read GetPayPeriodEndDate;
property FiscalYearEndDate: TDate read GetFiscalYearEndDate;
property FiscalYearStartDate: TDate read GetFiscalYearStartDate;
property EntryTypeID: TIdentifier read GetEntryTypeID;
property EntryTypeCaption: TCaption read GetEntryTypeCaption;
property RowNbr: TRowNbr read GetRowNbr;
property Clockable: Boolean read GetClockable;
property ClockableHours: THours read GetClockableHours;
property DateIn: TDate read GetDateIn;
property EmployeeName: string read GetEmployeeName;
property ScheduledTimeIn: TTime read GetScheduledTimeIn;
property ScheduledTimeOut: TTime read GetScheduledTimeOut;
property TimeIn: TTime read GetTimein;
property DateOut: TDate read GetDateOut;
property TimeOut: TTime read GetTimeOut;
property TimeElapsed: THours read GetTimeElapsed;
property Placeholder: Boolean read GetPlaceholder;
property TimeScheduled: THours read GetTimeScheduled;
property Difference: THours read GetDifference;
property WeekDay: string read GetWeekDay;
property WeekOf: TDate read GetWeekOf;
property CreatedBy: TUserName read GetCreatedBy;
property CreatedTimestamp: TDateTime read GetCreatedTimestamp;
property LastModifiedBy: TUserName read GetLastModifiedBy;
property LastModifiedTimestamp: TDateTime read GetLastModifiedTimestamp;
property Note: AnsiString read GetNote;
property Timesheet: ITimesheet read GetTimesheet;
end;
TDbSourceEntry = class(TDbCustomTimesheetEntry, ISourceEntryList)
strict private
FLoadTimesheetEntries: TLoadTimesheetProc;
FElectionList: ILevelPayElectionList;
FPositionList: IHourlyPositionList;
strict protected
procedure BeforePost(Dataset: TDataset); override;
procedure Load; override;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
AProc: TLoadTimesheetProc;
AElectionList: ILevelPayElectionList;
APositionList: IHourlyPositionList;
ACreateFields: Boolean = True
); reintroduce;
end;
TDbDummyEntry = class(TDbCustomTimesheetEntry, IDummyEntryList)
strict private
FPlaceholderID: TIdentifier;
FClosureList: ISchoolClosureList;
procedure EntryTypeIDOnChange(Sender: TField);
strict protected
procedure AddPlacedholder(ADate: TDate; ARowNbr: TRowNbr);
procedure CreateFields; override;
procedure DoAdd(AModel: ITimesheetEntry); override;
property PlaceholderID: TIdentifier read FPlaceholderID write FPlaceholderID;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
AClosureList: ISchoolClosureList;
ACreateFields: Boolean
); reintroduce;
end;
TDbTimesheetEntry = class(TDbDummyEntry, ITimesheetEntryList)
strict private
FClone: TFDDataset;
FSource: ISourceEntryList;
function GetNextRowNbr: TRowNbr;
strict protected
function WorkweekList: IWorkweekList;
procedure Clear;
procedure Load; override;
public
procedure Add(AModel: ITimesheetEntry); //replaces inherited add
procedure Delete(AModel: ITimesheetEntry); //replace inherited delete
procedure Update(OldModel, NewModel: ITimesheetEntry);
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ASourceFunc: TSourceListFunc;
AClosureList: ISchoolClosureList;
ACreateFields: Boolean
); reintroduce;
end;
implementation
uses
System.SysUtils
, System.Classes
, System.Variants
, System.DateUtils
, FireDAC.Comp.Client
, DateTimeHelper
, LevelPay.Model.Helpers
;
{ TCustomShift }
procedure TDbCustomTimesheetEntry.ClearFilter;
begin
CancelRange;
end;
constructor TDbCustomTimesheetEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet; ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACreateFields);
FCopyFunc := ACopyFunc;
FTimesheet := ATimesheet;
end;
procedure TDbCustomTimesheetEntry.CreateCalcFields;
begin
inherited;
FClockable := CreateCalcBooleanField(k_Clockable);
FClockableHours := CreateCalcFloatField(k_ClockableHours);
FDayOfWeek := CreateCalcStringField(k_WeekDay, 13);
FDifference := CreateCalcFloatField(k_Difference);
FEmployeeName := CreateCalcStringField(k_EmployeeName, 40);
FEntryTypeCaption := CreateCalcStringField(k_EntryTypeCaption, 20);
FFiscalYearEndDate := CreateCalcDateTimeField(k_FiscalYearEndDate);
FFiscalYearStartDate := CreateCalcDateTimeField(k_FiscalYearStartDate);
FScheduledTimeIn := CreateCalcDateTimeField(k_ScheduledTimeIn);
FScheduledTimeOut := CreateCalcDateTimeField(k_ScheduledTimeOut);
FTimeElapsed := CreateCalcFloatField(k_TimeElapsed);
FTimeScheduled := CreateCalcFloatField(k_TimeScheduled);
FWeekOf := CreateCalcDateTimeField(k_WeekOf);
end;
procedure TDbCustomTimesheetEntry.CreateFields;
begin
FID := CreateField(k_Id);
FEmployeeID := CreateField(k_EmployeeID);
FEntryTypeID := CreateField(k_EntryTypeID);
FRowNbr := CreateField(k_RowNbr);
FTimeIn := CreateField(k_TimeIn);
FTimeOut := CreateField(k_TimeOut);
FID := CreateField(k_ID);
FDateIn := CreateField(k_DateIn);
FDateOut := CreateField(k_DateOut);
FCreatedBy := CreateField(k_CreatedBy);
FCreatedTimestamp := CreateField(k_CreatedTimeStamp);
FLastModifiedBy := CreateField(k_LastModifiedBy);
FLastModifiedTimestamp := CreateField(k_LastModifiedTimestamp);
FNote := CreateField(k_Note);
FPayPeriodEndDate := CreateField(k_PayPeriodEndDate);
end;
procedure TDbCustomTimesheetEntry.CreateIndexes;
const
FIELD_LIST = k_DateIn + ';' + k_RowNbr;
begin
inherited;
FDateIndex := CreateIndex('ByDate', FIELD_LIST);
FDateIndex.Selected := True;
Dataset.IndexesActive := True;
end;
function TDbCustomTimesheetEntry.GetClockable: Boolean;
begin
Result := Rules.Clockable;
end;
function TDbCustomTimesheetEntry.GetClockableHours: THours;
begin
Result := Rules.ClockableHours;
end;
function TDbCustomTimesheetEntry.GetCreatedBy: TUserName;
begin
Result := FCreatedBy.AsUserName;
end;
function TDbCustomTimesheetEntry.GetCreatedTimestamp: TDateTime;
begin
Result := FCreatedTimestamp.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetDateIn: TDate;
begin
Result := FDateIn.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetDateOut: TDate;
begin
Result := FDateOut.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetDifference: THours;
begin
Result := Rules.Difference;
end;
function TDbCustomTimesheetEntry.GetEmployeeID: TIdentifier;
begin
Result := FEmployeeID.AsIdentifier;
end;
function TDbCustomTimesheetEntry.GetEmployeeName: string;
begin
Result := Rules.EmployeeName;
end;
function TDbCustomTimesheetEntry.GetEntryTypeID: TIdentifier;
begin
Result := FEntryTypeID.AsIdentifier;
end;
function TDbCustomTimesheetEntry.GetFiscalYearEndDate: TDate;
begin
Result := FFiscalYearEndDate.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetFiscalYearStartDate: TDate;
begin
Result := FFiscalYearStartDate.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetHasEntries: Boolean;
begin
Result := RecordCount > 0;
end;
function TDbCustomTimesheetEntry.GetID: TIdentifier;
begin
Result := FID.AsInteger;
end;
function TDbCustomTimesheetEntry.GetLastModifiedBy: TUserName;
begin
Result := FLastModifiedBy.AsUserName;
end;
function TDbCustomTimesheetEntry.GetLastModifiedTimestamp: TDateTime;
begin
Result := FLastModifiedTimestamp.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetModel: ITimesheetEntry;
var
LResult: ITimesheetEntry;
begin
LResult := FCopyFunc(Self);
Result := LResult;
end;
function TDbCustomTimesheetEntry.GetNote: AnsiString;
begin
Result := FNote.AsAnsiString;
end;
function TDbCustomTimesheetEntry.GetPayPeriodEndDate: TDate;
begin
Result := FPayPeriodEndDate.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetPlaceholder: Boolean;
begin
Result := Rules.Placeholder;
end;
function TDbCustomTimesheetEntry.GetEntry: ITimesheetEntry;
begin
Result := Model;
end;
function TDbCustomTimesheetEntry.GetEntryTypeCaption: TCaption;
begin
Result := Rules.EntryTypeCaption
end;
function TDbCustomTimesheetEntry.GetRowNbr: TRowNbr;
begin
Result := FRowNbr.AsRowNbr;
end;
function TDbCustomTimesheetEntry.GetScheduledTimeIn: TTime;
begin
Result := Rules.ScheduledTimeIn;
end;
function TDbCustomTimesheetEntry.GetScheduledTimeOut: TTime;
begin
Result := Rules.ScheduledTimeOut;
end;
function TDbCustomTimesheetEntry.GetTimeElapsed: THours;
begin
Result := Rules.TimeElapsed;
end;
function TDbCustomTimesheetEntry.GetTimein: TTime;
begin
Result := FTimeIn.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetTimeOut: TTime;
begin
Result := FTimeOut.AsDateTime;
end;
function TDbCustomTimesheetEntry.GetTimeScheduled: THours;
begin
Result := Rules.TimeScheduled;
end;
function TDbCustomTimesheetEntry.GetTimesheet: ITimesheet;
begin
Result := FTimesheet;
end;
function TDbCustomTimesheetEntry.GetWeekDay: string;
begin
Result := Rules.WeekDay;
end;
function TDbCustomTimesheetEntry.GetWeekOf: TDate;
begin
Result := Rules.WeekOf;
end;
procedure TDbCustomTimesheetEntry.Load;
begin
//Stub procedure
end;
procedure TDbCustomTimesheetEntry.OnCalcFields(Dataset: TDataset);
begin
inherited;
if not Assigned(Rules) then Exit;
FClockable.AsBoolean := GetClockable;
FClockableHours.AsHours := GetClockableHours;
FDayOfWeek.AsString := GetWeekDay;
FDifference.AsHours := GetDifference;
FEmployeeName.AsString := GetEmployeeName;
FEntryTypeCaption.AsCaption := GetEntryTypeCaption;
FTimeElapsed.AsHours := GetTimeElapsed;
FTimeScheduled.AsHours := GetTimeScheduled;
FScheduledTimeIn.AsDateTime := GetScheduledTimeIn;
FScheduledTimeOut.AsDateTime := GetScheduledTimeOut;
FWeekOf.AsDateTime := GetWeekOf;
end;
procedure TDbCustomTimesheetEntry.OnNewRecord(Dataset: TDataset);
begin
inherited;
FEmployeeID.AsIdentifier := FTimesheet.EmployeeID;
FFiscalYearEndDate.AsDateTime := FTimesheet.FiscalYearEndDate;
FFiscalYearStartDate.AsDateTime := FTimesheet.FiscalYearStartDate;
FPayPeriodEndDate.AsDateTime := FTimesheet.PayPeriodEndDate;
end;
procedure TDbCustomTimesheetEntry.DoUpdate(AModel: ITimesheetEntry);
begin
inherited;
FEmployeeID.AsIdentifier := AModel.EmployeeID;
FRowNbr.AsRowNbr := AModel.RowNbr;
FEntryTypeID.AsIdentifier := AModel.EntryTypeID;
FDateIn.AsDateTime := AModel.DateIn;
FTimeIn.AsDateTime := AModel.TimeIn;
FDateOut.AsDateTime := AModel.DateOut;
FTimeOut.AsDateTime := AModel.TimeOut;
FNote.AsAnsiString := AModel.Note;
end;
procedure TDbCustomTimesheetEntry.FilterEntries(const ADate: TDate);
begin
FDateIndex.Selected := True;
SetRange([ADate], [ADate]);
end;
function TDbCustomTimesheetEntry.Find(AModel: ITimesheetEntry): Boolean;
begin
Result := Locate(k_ID, AModel.ID);
end;
procedure TDbCustomTimesheetEntry.FormatFields;
begin
inherited;
FTimeElapsed.OnGetText := HoursFieldGetText;
FClockableHours.OnGetText := HoursFieldGetText;
FDifference.OnGetText := HoursFieldGetText;
FTimeScheduled.OnGetText := HoursFieldGetText;
SetTimeFieldDisplayFormat(FTimeIn);
SetTimeFieldDisplayFormat(FTimeOut);
SetDateFieldDisplayFormat(FDateIn);
SetDateFieldDisplayFormat(FDateOut);
SetDateFieldDisplayFormat(FPayPeriodEndDate);
SetSQLTimestampFieldDisplayFormat(FCreatedTimestamp);
SetSQLTimestampFieldDisplayFormat(FLastModifiedTimestamp);
end;
{ TDbDummyEntry }
procedure TDbSourceEntry.BeforePost(Dataset: TDataset);
var
LTimestamp: TDateTime;
begin
inherited;
LTimestamp := Now;
FLastModifiedBy.AsUserName := FTimesheet.User.UserName;
FLastModifiedTimestamp.AsDateTime := LTimestamp;
if State in [dsInsert] then
begin
FCreatedBy.AsUserName := FTimesheet.User.UserName;
FCreatedTimestamp.AsDateTime := LTimestamp;
end;
end;
constructor TDbSourceEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ATimesheet: ITimesheet;
ACopyFunc: TCopyFunc<ITimesheetEntry>; AProc: TLoadTimesheetProc;
AElectionList: ILevelPayElectionList; APositionList: IHourlyPositionList;
ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, ACreateFields);
FLoadTimesheetEntries := AProc;
FElectionList := AElectionList;
FPositionList := APositionList;
end;
procedure TDbSourceEntry.Load;
var
LEmployeeID: TIdentifier;
LFirstEntryDate: TDate;
LLastEntryDate: TDate;
begin
LEmployeeID := FTimesheet.EmployeeID;
LFirstEntryDate := FTimesheet.FirstEntryDate;
LLastEntryDate := FTimesheet.LastEntryDate;
FLoadTimesheetEntries(LEmployeeID, LFirstEntryDate, LLastEntryDate);
end;
{ TDbDummyEntry }
procedure TDbDummyEntry.AddPlacedholder(ADate: TDate; ARowNbr: TRowNbr);
var
LEntryTypeID: TIdentifier;
LClosure: ISchoolClosure;
LNote: AnsiString;
LRowNbr: TRowNbr;
begin
Dec(FPlaceholderID);
LNote := '';
LEntryTypeID := 0;
LRowNbr := ARowNbr;
if LRowNbr < 2 then //This is a first entry for the date
begin
if FClosureList.Find(ADate) then
begin
LClosure := FClosureList.Closure;
LEntryTypeID := LClosure.EntryTypeID;
LNote := AnsiString(LClosure.Caption);
end
else
begin
if TDateTime(ADate).DayOfWeek in [MONDAY..FRIDAY] then
LEntryTypeID := k_Regular
else
LEntryTypeID := 0;
end;
end;
Append;
FId.AsIdentifier := FPlaceholderID;
FRowNbr.AsRowNbr := LRowNbr;
FDateIn.AsDateTime := ADate;
FDateOut.AsDateTime := ADate;
FEntryTypeID.AsIdentifier := LEntryTypeID;
FNote.AsAnsiString := LNote;
Post;
end;
constructor TDbDummyEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet; AClosureList: ISchoolClosureList; ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, ACreateFields);
FClosureList := AClosureList;
end;
procedure TDbDummyEntry.CreateFields;
begin
inherited;
FId.ReadOnly := False;
FId.AutoGenerateValue := arNone;
FEntryTypeID.OnChange := EntryTypeIDOnChange;
end;
procedure TDbDummyEntry.DoAdd(AModel: ITimesheetEntry);
begin
inherited;
FId.AsIdentifier := AModel.ID;
end;
procedure TDbDummyEntry.EntryTypeIDOnChange(Sender: TField);
var
LDateIn: TDate;
LDateOut: TDate;
begin
if Sender.AsIdentifier = k_LandSchool then
begin
LDateIn := FDateIn.AsDateTime;
LDateOut := LDateIn + 1;
FDateOut.AsDateTime := LDateOut;
FTimeIn.AsDateTime := GetScheduledTimeOut;
FTimeOut.AsDateTime := GetScheduledTimeIn;
end;
end;
{ TDbTimesheetEntry }
procedure TDbTimesheetEntry.Add(AModel: ITimesheetEntry);
var
LEntry: ITimesheetEntry;
begin
FSource.Add(AModel);
LEntry := FSource.Entry; //Get model with updated ID
FTimesheet.WorkweekList.AddEntry(LEntry);
inherited Add(LEntry);
end;
procedure TDbTimesheetEntry.Clear;
begin
PlaceholderID := 0;
Dataset.CancelUpdates;
DisableControls;
try
First;
while RecordCount > 0 do
Dataset.Delete;
finally
EnableControls;
end;
end;
constructor TDbTimesheetEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>; ATimesheet: ITimesheet;
ASourceFunc: TSourceListFunc; AClosureList: ISchoolClosureList;
ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, AClosureList, ACreateFields);
FSource := ASourceFunc(FTimesheet);
FClone := TFDMemTable.Create(ADataset);
FClone.CloneCursor(ADataset);
end;
procedure TDbTimesheetEntry.Delete(AModel: ITimesheetEntry);
var
LDate: TDate;
LRowNbr: SmallInt;
LEntry: ITimesheetEntry;
begin
FSource.Delete(AModel);
WorkweekList.DeleteEntry(AModel);
DisableControls;
try
LDate := AModel.DateIn;
LRowNbr := AModel.RowNbr;
inherited Delete(AModel);
if (LRowNbr = 1) then
begin
AddPlacedholder(LDate, 0);
LEntry := Model; //Get placeholder
WorkweekList.AddEntry(LEntry);
end;
finally
EnableControls;
end;
end;
function TDbTimesheetEntry.GetNextRowNbr: TRowNbr;
begin
Result := 0;
FClone.SetRange([GetDateIn], [GetDateIn]);
while not FClone.Eof do
begin
Result := FClone.FieldByName(k_RowNbr).AsRowNbr + 1;
FClone.Next;
end;
FClone.CancelRange;
end;
procedure TDbTimesheetEntry.Load;
var
LDate: TDate;
LFirstEntryDate: TDate;
LCutoffDate: TDate;
LEntry: ITimesheetEntry;
LWeekOf: TDate;
LWorkweekList: IWorkweekList;
begin
LWorkweekList := FTimesheet.WorkweekList;
LFirstEntryDate := FTimesheet.FirstEntryDate;
LCutOffDate := FTimesheet.LastEntryDate;
LWeekOf := TDateTime(LFirstEntryDate).StartOfWeek;
LWorkweekList.Init(LFirstEntryDate, LCutOffDate);
FSource.Load;
DisableControls;
try
Clear;
LDate := LWeekOf;
repeat
FSource.FilterEntries(LDate);
if FSource.HasEntries then
begin
for LEntry in FSource do
begin
if LDate >= LFirstEntryDate then
begin
inherited Add(LEntry); //this must call inherited add to adding to FSource
end;
LWorkweekList.AddEntry(LEntry);
end;
end
else
begin
if LDate >= LFirstEntryDate then
begin
AddPlacedholder(LDate, 0);
LEntry := GetModel; //This retrieves the placeholder
LWorkweekList.AddEntry(LEntry);
end;
end;
LDate := LDate + 1;
until LDate > LCutOffDate;
finally
FSource.ClearFilter;
EnableControls;
First;
end;
end;
procedure TDbTimesheetEntry.Update(OldModel, NewModel: ITimesheetEntry);
var
LEntry: ITimesheetEntry;
begin
DisableControls;
try
if Assigned(OldModel) then
begin
if OldModel.Placeholder then
begin
FSource.Add(NewModel);
end
else
begin
FSource.Update(NewModel);
end;
inherited Delete(OldModel);
WorkweekList.DeleteEntry(OldModel);
end
else
begin
FSource.Add(NewModel);
end;
LEntry := FSource.Entry; //Get entry with new ID
inherited Add(LEntry);
WorkweekList.AddEntry(LEntry);
finally
EnableControls;
end;
end;
function TDbTimesheetEntry.WorkweekList: IWorkweekList;
begin
Result := FTimesheet.WorkweekList;
end;
end.
最佳答案
一般来说,当你有很多构造函数参数(这意味着依赖)时,这表明你的类可能做的太多了(参见单一责任原则)。
如果某些依赖项大部分时间只相互交互,这表明这些依赖项可能会被重构为它们自己的组件/类,然后注入(inject)。这不仅首先减少了依赖关系,而且降低了组件的复杂性。
我建议阅读 Mark Seemann 的博客,他解释了正确实践依赖注入(inject)和软件设计和架构的许多领域。
我只记得两个例子:
关于delphi - 构造函数依赖注入(inject)替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53279936/
我正在尝试测试依赖于其他服务 authService 的服务 documentViewer angular .module('someModule') .service('docu
如果我的网站上线(不要认为它会,目前它只是一个学习练习)。 我一直在使用 mysql_real_escape_string();来自 POST、SERVER 和 GET 的数据。另外,我一直在使用 i
我有以下代码,它容易受到 SQL 注入(inject)的攻击(我认为?): $IDquery = mysqli_query($connection, "SELECT `ID` FROM users W
我一直在自学如何创建扩展,以期将它们用于 CSS 注入(inject)(以及最终以 CSS 为载体的 SVG 注入(inject),但那是以后的问题)。 这是我当前的代码: list .json {
这个简单的代码应该通过 Java Spring 实现一个简单的工厂。然而结果是空指针,因为 Human 对象没有被注入(inject)对象(所以它保持空)。 我做错了什么? 谢谢 配置 @Config
我正在编写一个 ASP.NET MVC4 应用程序,它最终会动态构建一个 SQL SELECT 语句,以便稍后存储和执行。动态 SQL 的结构由用户配置以用户友好的方式确定,具有标准复选框、下拉列表和
首先让我说我是我为确保 SQL 注入(inject)攻击失败而采取的措施的知己。所有 SQL 查询值都是通过事件记录准备语句完成的,所有运算符(如果不是硬编码)都是通过数字白名单系统完成的。这意味着如
这是 SQL 映射声称可注入(inject)的负载: user=-5305' UNION ALL SELECT NULL,CONCAT(0x716b6b7071,0x4f5577454f76734
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,并且我还使用 Koin 作为我的依赖注入(inject)提供
假设 RequestScope 处于 Activity 状态(使用 cdi-unit 的 @InRequestScope) 给定 package at.joma.stackoverflow.cdi;
我有一个搜索表单,可以在不同的提供商中搜索。 我从拥有一个基本 Controller 开始 public SearchController : Controller { protected r
SQLite 注入 如果您的站点允许用户通过网页输入,并将输入内容插入到 SQLite 数据库中,这个时候您就面临着一个被称为 SQL 注入的安全问题。本章节将向您讲解如何防止这种情况的发生,确保脚
我可以从什么 dll 中获得 Intercept 的扩展?我从 http://github.com/danielmarbach/ninject.extensions.interception 添加了
使用 NInject 解析具有多个构造函数的类似乎不起作用。 public class Class1 : IClass { public Class1(int param) {...} public
我有一个 MetaManager 类: @Injectable() export class MetaManager{ constructor(private handlers:Handler
我是 Angular 的新手,我不太清楚依赖注入(inject)是如何工作的。我的问题是我有依赖于服务 B 的服务 A,但是当我将服务 A 注入(inject)我的测试服务 B 时,服务 B 变得未定
我正在为我的项目使用 android 应用程序启动、刀柄和空间。我在尝试排队工作时遇到错误: com.test E/WM-WorkerFactory: Could not instantiate co
我不确定这是什么糖语法,但让我向您展示问题所在。 def factors num (1..num).select {|n| num % n == 0} end def mutual_factors
简单的问题,我已经看过这个了:Managing imports in Scalaz7 ,但我不知道如何最小化注入(inject) right和 left方法到我的对象中以构造 \/ 的实例. 我确实尝
在我的 Aurelia SPA 中,我有一些我想在不同模块中使用的功能。它依赖于调用时给出的参数和单例的参数。有没有办法创建一个导出函数,我可以将我的 Auth 单例注入(inject)其中,而不必在
我是一名优秀的程序员,十分优秀!