Jump to content

Dmitriy M

Members
  • Content Count

    11
  • Joined

  • Last visited

Posts posted by Dmitriy M


  1. 30 minutes ago, Attila Kovacs said:

    In the constructor I mostly store the argument into a class field so It will cause an exception later, thus the constructor is not affected.

     

    Similar to Uwe's solution, but without initialize, just let it fail somewhere, but not in the constructor.

    The problem with this pattern is that most methods of the class now has to perform some kind of validation before doing their job.

    • Like 5

  2. On 10/29/2021 at 10:52 AM, Lars Fosdal said:
    
    try
      Parse;
    except
      on E:Excepetion do 
        if E is ParsingException
         then LogSomethingInformative
          else raise.
    end;

    While assuming that this code snippet is just to demonstrate the point, it always raises a question in my head: why trap every possible exceptions and then re-raise if it's not the one we are expecting, if we could just trap the one we are intrested in.

    try
      Parse;
    except
      on E: ParsingException do
        LogSomethingInformative;
    end;

     

    • Like 1

  3. Using TIdHTTP is it possible to distinguish whether POST request has been received (processed) by the server and error occurred during transmission/read of response or whether request has not been received by the server at all? I feel like my planned solution has too many assumptions and is far from perfect.

    begin
      // create and set up TIdHTTP instance
      IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent];
      try
        // prepare request
        IdHTTP.Post(API_END_POINT, RequestStream, ResponseStream);
        // check for response code and take actions
      except
        on E: EIdSocketError do
        begin
          // connection establishment error; the request was not processed
        end;
        on E: EIdConnectTimeout do
        begin
          // connection establishment error; the request was not processed
        end;
    
        on E: EIdReadTimeout do
        begin
          // response read error; the request was processed
        end;
        on E: EIdConnClosedGracefully do
        begin
          // response read error; the request was processed
        end;
      end;
    end;

     


  4. It seems like a simple factory class could solve your issue. Let it have bunch of class methods like CreateItemsFrame, CreateUsersFrame etc. Let it know about your TProjectDataType enums that will get passed to corresponding factory methods. Main form only needs to know about this factory class. If there is some actions that needs to be taken based on what type of frame is displayed on main form, then let the frames to expose some event that main form can subscribe to and trigger this event when required.

    • Like 1

  5. 1 hour ago, Attila Kovacs said:

    Unfortunately this will barely work for example in Berlin U2 (or prior) as it was released meanwhile a 

    coffee break and my "REST.JsonReflect.pas" has things like

     

    raise Exception.Create('NOT IMPLEMENTED');

    or

    "revAttr.ObjectsReverter(Data, FieldName, GetArgObjects(revEv.FFieldClassType,"

    where revEv is not setted in the 3rd case of the if, and it's either nil or points to garbage.

    It's not that difficult to modify REST.JsonReflect.pas to make it work in 10.2 (maybe prior versions too)

    procedure TJSONUnMarshal.PopulateFields
    {...}
              case revAttr.ReverterType of
                rtTypeObjects:
                  begin
                    Delete(FieldName, 1, 1);
                    if (jsonFieldVal is TJSONArray) or (jsonFieldVal is TJSONNull) then
                    begin
    //                  raise Exception.Create('NOT IMPLEMENTED');
                      SetField(Data, FieldName, revAttr.TypeObjectsReverter(GetArgObjects(LObjectType,
                        TJSONArray(jsonFieldVal))))
                    end
                    else
                      raise EConversionError.Create(Format(SArrayExpectedForField, [FieldName, jsonFieldVal.ToString]));
                  end;
                rtTypeStrings:
    {...}
    function JsonReflectAttribute.JSONInterceptor: TJSONInterceptor;
    begin
    //  Result := FInterceptor.NewInstance as TJSONInterceptor;;
      Result := FInterceptor.Create as TJSONInterceptor;
      Result.ConverterType := FConverterType;
      Result.ReverterType := FReverterType;
    end;

    This works like a charm with @Uwe Raabe code from this post.


  6. Quote

    Note that we need at least one type keyword between the alias and its use inside the attribute.

    This is really confusing. So the new "type" section makes compiler consider class completely defined :classic_blink:

    What is an explanation of this?

    type
      TMyObjectList = TObjectList<TMyObject>;
      TMyObjectListInterceptor = TObjectListInterceptor<TMyObject>;
    type
    // if above "type" keyword is commented out then
    // [dcc32 Error]: E2086 Type 'TObjectListInterceptor<T>' is not yet completely defined
      TMyClass = class
      private
        [JsonReflect(ctTypeObjects, rtTypeObjects, TMyObjectListInterceptor)]
        FContent: TMyObjectList;
      end;

     


  7. program Project1;
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.SysUtils,
      REST.JSON,
      Unit1 in 'Unit1.pas';
    
    var
      Person1, Person2: TPerson;
      jsonstr: string;
    begin
      Person1 := TPerson.Create;
      try
         Person1.Name := 'Hello';
         jsonstr := Person1.SaveSettings;
         writeln(jsonstr); //write {"name":"Hello"}
         Person1.Name := 'hi';
         Person1.LoadSettings(jsonstr);
         writeln(Person1.Name); //write Hello
         readln;
      finally
        Person1.Free;
      end;
      
      jsonstr := '{"name":"Stephane"}';
      Person2 := TPerson.FromString(jsonstr);
      try
        writeln(Person2.Name); //write Stephane
        readln;
      finally
        Person2.Free;
      end;
    end.
    unit Unit1;
    
    interface
    
    type
      TPerson = class(TObject)
      private
        [JSONNameAttribute('NAME')]
        FName: string;
      public
        class function FromString(const aJsonString: String): TPerson;
        procedure LoadSettings(const aJsonString: String);
        function SaveSettings: string;
        property Name: string read FName write FName;
      end;
    
    implementation
    
    uses REST.JSON;
    
    class function TPerson.FromString(const aJsonString: String): TPerson;
    begin
      Result := TJSON.JsonToObject<TPerson>(aJsonString);
    end;
    
    procedure TPerson.LoadSettings(const aJsonString: String);
    var
      oJSON: TJSONObject;
    begin
      oJSON := TJSONObject.ParseJSONValue(aJsonString) as TJSONObject;
      try
        TJSON.JsonToObject(self, oJSON);
      finally
        oJSON.Free;
      end;
    end;
    
    function TPerson.SaveSettings: String;
    begin
      Result := TJSON.ObjectToJsonString(self);
    end;
    
    end.

    Reference

    • Thanks 1
×