Jump to content

TiGü

Members
  • Content Count

    39
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by TiGü


  1. Hi Primož,

     

    that's a nice piece of code, but i notice in my Delphi Tokyo, that the ens-Result for the TEnumSet (for valid values) is empty.

    But if you add a untyped Move, than it works:

     

    program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.TypInfo,
      System.Rtti,
      System.SysUtils;
    
    resourcestring
      SValueLiesOutsideAllowedRange = 'Value %d lies outside allowed range for %s (%d .. %d)';
    
    type
      TypeInfoCache<T> = class
      class var
        FMinIntVal: Integer;
        FMaxIntVal: Integer;
        FIsSet: Boolean;
      public
        class constructor Create;
        class property MaxIntVal: Integer read FMaxIntVal;
        class property MinIntVal: Integer read FMinIntVal;
        class property IsSet: Boolean read FIsSet;
      end;
    
      Range<T> = record
      private
        class function MaxIntVal: Integer; static; inline;
        class function MinIntVal: Integer; static; inline;
        class procedure RaiseException(const Value: Integer); static;
      public
        class function Check(const Value: Integer): T; static;
      end;
    
      { Range<T> }
    
    class function Range<T>.Check(const Value: Integer): T;
    begin
      if (Value < MinIntVal) or (Value > MaxIntVal) then
        RaiseException(Value);
    
      if TypeInfoCache<T>.IsSet then
      begin
        Move(Value, Result, SizeOf(T)); // here is the magic
      end;
    end;
    
    class function Range<T>.MaxIntVal: Integer;
    begin
      Result := TypeInfoCache<T>.MaxIntVal;
    end;
    
    class function Range<T>.MinIntVal: Integer;
    begin
      Result := TypeInfoCache<T>.MinIntVal;
    end;
    
    class procedure Range<T>.RaiseException(const Value: Integer);
    begin
      raise Exception.CreateFmt(SValueLiesOutsideAllowedRange,
        [Value, PTypeInfo(TypeInfo(T)).Name, MinIntVal, MaxIntVal]);
    end;
    
    { TypeInfoCache<T> }
    
    class constructor TypeInfoCache<T>.Create;
    var
      ti: PTypeInfo;
      typeData: PTypeData;
      i: Integer;
    begin
      ti := TypeInfo(T);
      FIsSet := ti.Kind = tkSet;
      if FIsSet then
        ti := GetTypeData(ti).CompType^;
      typeData := GetTypeData(ti);
      FMinIntVal := typeData.MinValue;
    
      if FIsSet then
      begin
        FMaxIntVal := 0;
        for i := typeData.MinValue to typeData.MaxValue do
          FMaxIntVal := FMaxIntVal or (1 shl i);
      end
      else
        FMaxIntVal := typeData.MaxValue;
    end;
    
    type
      TEnum = (en1, en2, en3);
      TEnumSet = set of TEnum;
    
    var
      en: TEnum;
      ens: TEnumSet;
    
    begin
      try
    
        try
          en := Range<TEnum>.Check(0);
          en := Range<TEnum>.Check(2);
          en := Range<TEnum>.Check(3);
        except
          on E: Exception do
            Writeln('Expected exception: ', E.ClassName, ' ', E.Message);
        end;
    
        try
          ens := Range<TEnumSet>.Check(0);
          ens := Range<TEnumSet>.Check(2);
          ens := Range<TEnumSet>.Check(7);
          ens := Range<TEnumSet>.Check(8);
        except
          on E: Exception do
            Writeln('Expected exception: ', E.ClassName, ' ', E.Message);
        end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      if DebugHook <> 0 then
        Readln;
    
    end.

     

    • Like 1

  2. program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    
    uses
      System.SysUtils,
      Winapi.Windows;
    
    procedure Main;
    var
      I: Integer;
    begin
      Writeln('Start');
    
      while not IsDebuggerPresent do
      begin
        Writeln('I''m waiting for you!');
        Sleep(100);
      end;
    
      for I := 1 to 1000 do
        Writeln(' I:', I);
    
      Writeln('End');
    end;
    
    begin
      try
        Main;
        Readln;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    
    end.

    Try the good old While-Not-IsDebuggerPresent-Trick! 

    • Like 1
    • Thanks 1

  3. Wow, it could be easier.
    You have to set the Converter.Options after casting to the EarsivWebService interface. Then they are not reset and you can avoid the AfterExecute handler.

     

    unit Earsiv.View;
    
    interface
    
    uses
      System.SysUtils,
      System.Classes,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
      EarsivWebService1,
      Soap.SOAPHTTPClient,
      Soap.OpConvertOptions;
    
    type
      TForm5 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        FRIO: THTTPRIO;
        FEarsivWebService: EarsivWebService;
      public
      end;
    
    var
      Form5: TForm5;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm5.FormCreate(Sender: TObject);
    begin
      FRIO := THTTPRIO.Create(nil);
      FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService';
      FEarsivWebService := (FRIO as EarsivWebService);
    
      FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
    end;
    
    procedure TForm5.Button1Click(Sender: TObject);
    var
      Request: faturaOlustur;
      Response: faturaOlusturResponse;
    begin
      Request := nil;
      Response := nil;
    
      Request := faturaOlustur.Create();
      Request.input := 'Hello';
      Request.fatura := belge.Create();
      Request.fatura.belgeFormati := belgeFormatiEnum.PDF;
    
      try
        Response := FEarsivWebService.faturaOlustur(Request);
      finally
        if Assigned(Response) then
        begin
          if Assigned(Response.return) then
          begin
            ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText);
          end;
          Response.Free;
        end;
    
        Request.Free;
      end;
    end;
    
    end.

     


  4. Hi @ertank!  I play with your code and do some debugging in the depths of the Delphi SOAP sources. As you can see in the TOPToSoapDomConvert.ProcessResponse (Line 2037 in Tokyo 10.2.3) it calls a inline class helper function IsBareLiteral. 

     

    Making long story short: Set every time the THTTPRIO.Converter.Options (see Unit Soap.OpConvertOptions) and the Response will be filled.

     

    Try this:

     

    unit Earsiv.View;
    
    interface
    
    uses
      System.SysUtils,
      System.Classes,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
      EarsivWebService1,
      Soap.SOAPHTTPClient,
      Soap.OpConvertOptions;
    
    type
      TForm5 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        FRIO: THTTPRIO;
        WS: EarsivWebService;
        procedure MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream);
      public
      end;
    
    var
      Form5: TForm5;
    
    implementation
    
    {$R *.dfm}
    
    
    procedure TForm5.Button1Click(Sender: TObject);
    var
      Request: faturaOlustur;
      Response: faturaOlusturResponse;
    begin
      if not Assigned(FRIO) then
      begin
        FRIO := THTTPRIO.Create(nil);
        FRIO.OnAfterExecute := MyHTTPRIO1AfterExecute;
        FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService';
        // the following line are not enough, see MyHTTPRIO1AfterExecute
        FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
        WS := (FRIO as EarsivWebService);
      end;
    
      Request := nil;
      Response := nil;
    
      Request := faturaOlustur.Create();
      Request.input := 'Hello';
      Request.fatura := belge.Create();
      Request.fatura.belgeFormati := belgeFormatiEnum.PDF;
    
      try
        Response := WS.faturaOlustur(Request);
      finally
        if Assigned(Response) and Assigned(Response.return) then
        begin
          ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText);
        end;
    
        Request.Free;
        Response.Free;
      end;
    end;
    
    procedure TForm5.MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream);
    begin
      FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
    end;
    
    end.

     

    • Like 1
×