Skip to content

Commit c50000c

Browse files
committed
fixed #336 (fixed casting an "empty" TValue to any other type)
1 parent 8b00c2c commit c50000c

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

Source/Base/Spring.pas

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,8 @@ TValueHelper = record helper for TValue
657657
/// </summary>
658658
function IsString: Boolean;
659659

660+
function IsType(ATypeInfo: PTypeInfo): Boolean; overload;
661+
660662
/// <summary>
661663
/// Checks whether the stored value is a <c>Variant</c>.
662664
/// </summary>
@@ -669,6 +671,8 @@ TValueHelper = record helper for TValue
669671

670672
function TryAsType(typeInfo: PTypeInfo; out target): Boolean; overload;
671673

674+
function TryCast(ATypeInfo: PTypeInfo; out AResult: TValue): Boolean;
675+
672676
/// <summary>
673677
/// Tries to convert the stored value. Returns false when the conversion
674678
/// is not possible.
@@ -5740,6 +5744,13 @@ function TValueHelper.IsString: Boolean;
57405744
Result := Kind in StringKinds;
57415745
end;
57425746

5747+
function TValueHelper.IsType(ATypeInfo: PTypeInfo): Boolean;
5748+
var
5749+
unused: TValue;
5750+
begin
5751+
Result := TryCast(ATypeInfo, unused);
5752+
end;
5753+
57435754
function TValueHelper.IsVariant: Boolean;
57445755
begin
57455756
Result := TypeInfo = System.TypeInfo(Variant);
@@ -6034,6 +6045,32 @@ function TValueHelper.TryAsType(typeInfo: PTypeInfo; out target): Boolean;
60346045
value.ExtractRawData(@target);
60356046
end;
60366047

6048+
function TValueHelper.TryCast(ATypeInfo: PTypeInfo;
6049+
out AResult: TValue): Boolean;
6050+
begin
6051+
// fix wrong logic in RTL:
6052+
// typecasting a TValue that contains a reference type that is nil succeeds
6053+
// in all cases which clearly is against the otherwise strict type cast rules
6054+
6055+
if not ((TValueData(Self).FTypeInfo = nil) or (TValueData(Self).FValueData = nil)) then
6056+
if IsEmpty and Assigned(ATypeInfo) and (Kind <> ATypeInfo.Kind) then
6057+
case Kind of
6058+
tkClass:
6059+
if not (ATypeInfo.Kind in [tkVariant, tkInterface, tkPointer]) then
6060+
Exit(False);
6061+
tkInterface:
6062+
if not (ATypeInfo.Kind in [tkVariant, tkPointer]) then
6063+
Exit(False);
6064+
tkDynArray:
6065+
if TValueData(Self).FTypeInfo <> ATypeInfo then
6066+
Exit(False);
6067+
tkPointer:;
6068+
else
6069+
Exit(False);
6070+
end;
6071+
Result := TValueHack(Self).TryCast(ATypeInfo, AResult);
6072+
end;
6073+
60376074

60386075
{$REGION 'Conversion functions'}
60396076
type

Source/Core/Container/Spring.Container.Resolvers.pas

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,10 @@ function TDependencyResolver.CanResolve(const context: ICreationContext;
267267
if CanResolveFromSubResolvers(context, dependency, argument) then
268268
Exit(True);
269269

270-
if argument.IsEmpty then
271-
Result := Kernel.Registry.HasDefault(dependency.TypeInfo)
272-
else if CanResolveFromArgument(context, dependency, argument) then
270+
if CanResolveFromArgument(context, dependency, argument) then
273271
Result := True
272+
else if argument.IsEmpty then
273+
Result := Kernel.Registry.HasDefault(dependency.TypeInfo)
274274
else if argument.TryAsType(TypeInfo(TTypeKind), kind) and (kind = tkDynArray) then
275275
Result := Kernel.Registry.HasService(dependency.TypeInfo)
276276
else

0 commit comments

Comments
 (0)