TUtils.TryConvert will convert from a value to a Nullable Type, but not from a Nullable Type to a value

Issue #113 invalid
Todd Flora created an issue

We are using the Persistence.TUtils.TryConvert method in our own code to convert TValues from a given value type such as String or Integer to their Nullable equivelant and it works great.

Today I tried to use this same function in the reverse and it failed to convert. After looking at the code I can see that the reverse circumstance is not coded in this method. Should it Be? Or is there another method we should be using to convert from a NullableType to it's underlying value type?

class function TUtils.TryConvert(const AFrom: TValue; targetTypeInfo: PTypeInfo; AEntity: TObject; var AResult: TValue): Boolean;
var
  freeAfterUse: Boolean;
begin
  if AFrom.TypeInfo <> targetTypeInfo then
  begin
    case targetTypeInfo.Kind of
      tkRecord:
      begin
        if IsNullable(targetTypeInfo) then
        begin
          TValue.Make(nil, targetTypeInfo, AResult);
          AResult.SetNullableValue(AFrom);
          Exit(True);
        end else
        if TType.IsLazyType(targetTypeInfo) then
        begin
          //AFrom value must be ID of lazy type
          if AFrom.IsEmpty then
            raise EORMColumnCannotBeNull.Create('Column for lazy type cannot be null');
          Exit(True);
        end;
      end;
    end;
    {TFlora - ADDED THE FOLLOWING CODE TO CONVERT FROM NULLABLE TYPE TO SOMETHING ELSE}
    if (AFrom.TypeInfo.Kind = tkRecord) then
    begin
      if IsNullable(AFrom.TypeInfo) then
      begin
        TValue.Make(nil, targetTypeInfo, AResult);
        Exit(AFrom.TryGetNullableValue(AResult));
      end
    end;
   {TFlora - done with code addition}

    freeAfterUse := False;
    Result := Spring.Persistence.Core.Reflection.TryConvert(AFrom, targetTypeInfo, AResult, freeAfterUse);
  end
  else
  begin
    Result := True;
    AResult := AFrom;
  end;
end;

Comments (7)

  1. Stefan Glienke repo owner

    In fact you should not be using any functions from Spring.Persistence.Core.Reflection.pas, Spring.Persistence.Core.Utils.pas or Spring.Persistence.Mapping.RttiExplorer.pas. They are only for internal use and subject to change and we cannot guarantee they will stay as they are.

    If you want to convert values you should be looking into Spring.Reflection.ValueConverters.pas

  2. Todd Flora reporter

    Understood that there are no guarantees, we are basing much of our functionality on marshmallow and also benefiting from many of the same concepts used. The methods we are using work well for our purposes which line up well with why the persistence layer uses them.

    I will look at Valueconverters but this method will return false if you try to use it in the reverse. I just thought this might not be expected and Linus might want to consider adding the code for converting both ways.

  3. Stefan Glienke repo owner

    Most of the things in the units I mentioned are a result of the project originally not being based nor part of Spring4D so many things overlap with existing functionality in the library especially in the Rtti/Reflection area and are not implemented in a way that it should not be part of a fully supported public API.

  4. Todd Flora reporter

    Completely understood, I am trying out the ValueConverter and I agree that is more well thought out. I understand the struggles of integrating. Consider this Closed.

  5. Log in to comment