Sto cercando di capire il modo migliore per utilizzare l'integrazione delle dipendenze per un codice precedente che richiederà un lungo refactoring e che deve essere eseguito gradualmente. La maggior parte delle vecchie classi utilizzare una proprietà "Parent" per determinare varie cose e la proprietà genitore è stato spesso passano in via un argomento del costruttore come segue:Iniezione del costruttore rispetto all'iniezione setter per proprietà Parent
constructor TParentObject.Create;
begin
FChildObject := TChildObject.Create(Self);
end;
constructor TChildObject.Create(AParent: TParentObject)
begin
FParent := AParent;
end;
Questo è abbastanza tipico della nostra base di codice legacy. Tuttavia, quando si passa alle interfacce e all'iniezione del costruttore, il Parent non è conosciuto dal framework Spring4D quando crea l'oggetto Child. Quindi otterrà solo un nuovo genitore ma non quello esistente. Naturalmente posso creare un getter/setter di proprietà, ma ciò indicherebbe una proprietà "facoltativa" per la classe che è in realtà una proprietà obbligatoria. Vedere il codice qui sotto per ulteriori spiegazioni:
unit uInterfaces;
interface
uses
Spring.Collections;
type
IChildObject = interface;
IParentObject = interface
['{8EA8F9A2-E627-4546-8008-0A77DA2B16F1}']
function GetSomethingRequiredByChild: string;
procedure SetSomethingRequiredByChild(const Value: string);
property SomethingRequiredByChild: string read GetSomethingRequiredByChild write SetSomethingRequiredByChild;
function GetChild: IChildObject;
property Child: IChildObject read GetChild;
end;
// This introduces a property getter/setter
// However it also implies that Parent can be NIL which it cannot
IChildObject = interface
['{ECCA09A6-4A52-4BE4-A72E-2801160A9086}']
function GetParent: IParentObject;
procedure SetParent(const Value: IParentObject);
property Parent: IParentObject read GetParent write SetParent;
end;
TParentObject = class(TInterfacedObject, IParentObject)
private
FChild: IChildObject;
FSomethingRequiredByChild: string;
function GetChild: IChildObject;
function GetSomethingRequiredByChild: string;
procedure SetSomethingRequiredByChild(const Value: string);
public
constructor Create;
end;
TChildObject = class(TInterfacedObject, IChildObject)
private
FParent: IParentObject;
function GetParent: IParentObject;
procedure SetParent(const Value: IParentObject);
public
// This requries a Parent object, but how does the Spring4D resolve the correct parent?
constructor Create(const AParent: IParentObject);
end;
implementation
uses
Spring.Services;
{ TParentObject }
constructor TParentObject.Create;
begin
// Here is the old way...
FChild := TChildObject.Create(Self); // Old way of doing it
// This is the Service Locator way...
FChild := ServiceLocator.GetService<IChildObject>;
// I would prefer that the Parent is assigned somehow by the Service Locator
// IS THIS POSSIBLE - or am I dreaming?
FChild.Parent := Self;
end;
function TParentObject.GetChild: IChildObject;
begin
Result := FChild;
end;
function TParentObject.GetSomethingRequiredByChild: string;
begin
Result := FSomethingRequiredByChild;
end;
procedure TParentObject.SetSomethingRequiredByChild(const Value: string);
begin
FSomethingRequiredByChild := Value;
end;
{ TChildObject }
constructor TChildObject.Create(const AParent: IParentObject);
begin
FParent := AParent;
end;
function TChildObject.GetParent: IParentObject;
begin
Result := FParent;
end;
procedure TChildObject.SetParent(const Value: IParentObject);
begin
FParent := Value;
end;
end.
Forse c'è qualche metodo che può essere utilizzato che io non sono a conoscenza di impostare l'oggetto padre utilizzando il framework DI?
Spero che questa domanda sia chiara su cosa sto cercando di ottenere. Sono felice di fornire ulteriori esempi di descrizione/codice dove necessario.
Sarebbe interessante vedere il codice che "crea" effettivamente gli oggetti figli. Sento odore di localizzatore di servizi. –
Haha Stefan, hai ragione, è quello che stavo progettando di usare ma mi chiedevo se c'è un'alternativa? Pubblicherò il codice ora. –
La mia domanda sarebbe: perché pensi che sia meglio che chiamare direttamente il costruttore di TChildObject in TParentObject? Immagino che il codice reale sia un po 'più complesso, ma comunque: se hai una relazione genitore/figlio le classi potrebbero comunque conoscersi. In caso contrario, suggerirei di utilizzare il modello di fabbrica. Pubblicherà del codice. –