Search code examples
delphipolymorphismcontainersdelphi-xe2spring4d

Are there any methods built into the Spring framework that make working with polymorphic containers easier?


I have a dictionary that contains different kinds of values and I want to filter for an item that has a specific sub-type and that satisfies a certain condition:

var
  FData: IDictionary<TGUID, TObject>; // Polymorphic
begin
  TMicroStep(FData.Values.Single(
    function(const O: TObject): Boolean begin
      Result := (O is TMicroStep) and (TMicroStep(O).OrderTag = 1);
  end))
end;

It works, but it looks ugly, because of the type check and double cast.

Maybe something like this might be possible?

var
  FData: IDictionary<TGUID, TObject>; // Polymorphic
begin
  FData.Values.SingleSubType<TMicroStep>(
    function(const MS: TMicroStep): Boolean begin
      Result := MS.OrderTag = 1;
  end))
end;

Does Spring have anything that can help me here?


Solution

  • Unfortunately Delphi does not support parameterized methods in interfaces. That is why IEnumerable<T> does not have methods like OfType<TResult>.

    You could use a static method like we provide in TCollections (or with 1.2 in the new static type TEnumerable that provides those methods) but I don't know if you like that any better than what you already have:

    TEnumerable.OfType<TObject, TMicroStep>(FData.Values).Single(
      function(const MS: TMicroStep): Boolean
      begin
        Result := MS.OrderTag = 1;
      end);
    

    The method would look like this (untested but should work):

    class function TEnumerable.OfType<T, TResult>(
      const source: IEnumerable<T>): IEnumerable<TResult>;
    begin
      Result := TOfTypeIterator<T, TResult>.Create(source);
    end;
    

    TOfTypeIterator<T,TResult> is from Spring.Collections.Extensions.

    The type check in its MoveNext method certainly can be improved when dealing with classes to avoid TValue.