Einzelnen Beitrag anzeigen

Sequitar

Registriert seit: 8. Jan 2016
74 Beiträge
 
Delphi 10.4 Sydney
 
#14

AW: Custom Constructor /DI bei factory-basierter Objekterstellung

  Alt 10. Mär 2018, 23:30
Zwischenzeitlich woanders weitergebaut, bin heute wieder drüber gestolpert.
Hab mir folgendes überlegt. Man kann doch methoden oder constructors auch über die RTTI aufrufen.
Damit hätte ich genau was ich ursprünglich wollte....
Ein Beispiel hab ich hier gefunden:

Delphi-Quellcode:
Function NewFromClassInfo(Const ATypeInfo: PTypeInfo;{Params: Array Of Tvalue}): Tobject;
  Var
    Ctx: TRttiContext;
    RType: TRttiType;
    AMethCreate: TRttiMethod;
    InstanceType: TRttiInstanceType;
    Fvalue: Rtti.Tvalue;
  Begin
    Ctx := TRttiContext.Create;
    RType := Ctx.GetType(ATypeInfo);
    For AMethCreate In RType.GetMethods Do
    Begin
{$MESSAGE 'TODO Handle constructors with params.'}
      If Assigned(AMethCreate)
      Then
        If (AMethCreate.IsConstructor) And
          (Length(AMethCreate.GetParameters) = 0)//müsste dann entfernt werden
        Then
        Begin
          InstanceType := RType.AsInstance;
          FValue := AMethCreate.Invoke(InstanceType.MetaclassType, [{params}]);
{hatte überlegt, params hier zu übergeben. das führt jedoch zu access violation
ODER zur meldung ("parameter count mismatch").
Und JA, ich übergebe (nur anscheinend) die richtige parameterzahl.


(Also wenn create(anint:integer)>>tx.create(5);
>>newfromclassinfo(tx.classinfo,[5]);
}

          Result := Fvalue.AsObject;
          Exit;
        End;
    End;
  End;
Kann man das verbessern? Obiges beheben?
Merci.
Hier mal ein kleines Beispiel:

Delphi-Quellcode:
program Simple_DI;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  SimpleContainer in 'SimpleContainer.pas';

type
  IX = interface
    ['{E2D88E1C-AE7D-491A-B456-84B134749890}']
  end;

  IY = interface
    ['{3D1256AB-CDDE-49B2-94CF-E9FA82314206}']
  end;

  IZ = interface
    ['{4F51DE5D-B65B-4776-B25B-5B2868DC34AC}']
  end;

  TX = class(TInterfacedObject, IX)
  private
    fy: IY;
    fz: IZ;
  public
    constructor Create(const y: IY; const z: IZ);
  end;

  TY = class(TInterfacedObject, IY)
    constructor Create;
  end;

  TZ = class(TInterfacedObject, IZ)
    constructor Create;
  end;

{ TX }

constructor TX.Create(const y: IY; const z: IZ);
begin
  Writeln('creating ', ClassName);
  Writeln('injected ', (y as TObject).ClassName, ' for y');
  Writeln('injected ', (z as TObject).ClassName, ' for z');

  fy := y;
  fz := z;
end;

{ TY }

constructor TY.Create;
begin
  Writeln('creating ', ClassName);
end;

{ TZ }

constructor TZ.Create;
begin
  Writeln('creating ', ClassName);
end;

var
  container: TSimpleContainer;
  x: IX;
begin
  // showing the so called register, resole, release (RRR) pattern
  // see http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern/

  container := TSimpleContainer.Create;
  try
    // register
    container.Add<IX, TX>;
    container.Add<IY, TY>;
    container.Add<IZ, TZ>;

    // resolve
    x := container.Get<IX>;
  finally
    // release
    x := nil;
    container.Free;
  end;
end.
  Mit Zitat antworten Zitat