Continuing on the previous LINQ post, I’ll just show a couple of more features possible using kbmMW’s Linq.

Returning an object or a list of objects as result

Remember in LINQ #1 where I showed how to work with classes and objects using kbmMW Linq? We already defined the following object. If you dont remember please read previous LINQ #1 blog post.

  [kbmMW_Linq]
  TMyData = class
  private
     FName:string;
     FAddress:string;
     FAge:integer;
  public
     constructor Create(const AName:string;
                        const AAddress:string;
                        const AAge:integer);
     property Name:string read FName write FName;
     property Address:string read FAddress write FAddress;
     property Age:integer read FAge write FAge;
  end;

Again I add a number of instances to an object list, so we have something to work with.
But this time I will show how to get a TMyData instance back from kbmMW Linq alternatively how to get a list of matching TMyData back.

procedure TForm1.TestObjecs;
var
   lst,lst2:TObjectList<TMyData>;
   md:TMyData;
   i:integer;
begin
     lst:=TObjectList<TMyData>.Create;
     try
        lst.Add(TMyData.Create('Kim','Address 1',49));
        lst.Add(TMyData.Create('Hans','Address 2',22));
        lst.Add(TMyData.Create('Jens','Address 3',33));
        lst.Add(TMyData.Create('Joe','Address 3',77));
        lst.Add(TMyData.Create('John','Address 4',33));

        md:=Linq.Using(lst).Where('Age=77').AsGeneric.&Object<TMyData>;
        try
           if md<>nil then
              Memo1.Lines.Add('Age=77 match '+md.Name)
           else
               Memo1.Lines.Add('No match for Age=77');
        finally
           md.Free;
        end;

        lst2:=Linq.Using(lst).Where('Age=33').AsGeneric.List<TMyData>;
        try
           if lst2<>nil then
           begin
                for md in lst2 do
                    Memo1.Lines.Add('Age=33 match '+md.Name);
           end
           else
               Memo1.Lines.Add('No match for Age=33');
        finally
           lst2.Free;
        end;
     finally
        lst.Free;
     end;
end;

The returned objects are not references to existing objects, but are generated by the Linq framework, so you must remember to free them when they are no longer of interest.

If nothing match, nil will be returned.

This sample shows how to return object of the same type as the ones originally being in the Using clause. However you can use any class (registered with kbmMW) as a result. Only fields/properties that has matching names will be filled.

So having an object like this:

type
   [kbmMW_Linq]
   TMyData2 = class
   private
     FID:string; 
     FName:string;
     FAddress:string;
     FZipCode:string;
   public
     property ID:string read FID write FID; 
     property Name:string read FName write FName;
     property Address:string read FAddress write FAddress;  
     property ZipCode:string read FZipCode write FZipCode;
   end;

Remember to register the TMyData2 class along with the previously registered TMyData class:

  TkbmMWRTTI.EnableRTTI([TMyData,TObjectList<TMyData>,TMyData2]);
  kbmMWRegisterKnownClasses([TMyData,TObjectList<TMyData>,TMyData2]);

While remembering that lst is still an instance of TObjectList<TMyData>, it’s perfectly legal to do:

var
  md2:TMyData2;
...
    md2:=Linq.Using(lst).Where('Age=77').AsGeneric.&Object<TMyData2>;

You will be returned a TMyData2 object instance where only the Name and Address properties has values.

The same method can be applied to JSON, BSON, Messagepack, YAML and XML data too, which makes it a very easy thing to convert parts of structured documents to objects and object lists.

 

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.