Exception when injecting nil values to a complex constructor via the DI-container

Issue #366 resolved
Daniel Trierweiler created an issue

Hi,

We are trying to inject an empty value to a constructor via the DI container. Doing so, the TCreationContext fails to resolve the correct constructor though, resulting in an EActivatorException.

The error can be reproduced with code like this (see the attached project file for complete code):

type
  IMyInterface = interface
    ['{10422B97-B488-4F2A-852C-0ED1724F2D45}']
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
    constructor Create(const pDependency: IMyInterface; const pSomething: String);
  end;

{ IMyClass }

constructor TMyClass.Create(const pDependency: IMyInterface; const pSomething: String);
begin
  inherited Create();
end;

begin
  GlobalContainer.RegisterType<IMYInterface, TMyClass>;
  GlobalContainer.Build;

  // This works.
  var lDep1: IMyInterface := TMyClass.Create(nil, '');
  var lRes1: IMyInterface := GlobalContainer.Resolve<IMyInterface>([TValue.From<IMyInterface>(lDep1), 'random']);

  // This raises an EActivatorException
  var lDep2: IMyInterface := nil;
  var lRes2: IMyInterface := GlobalContainer.Resolve<IMyInterface>([TValue.From<IMyInterface>(lDep2), 'random']);
end.

We know we can resolve this by adjusting the order of the parameters and adding overloaded constructors without the nil parameters. This requires additional code though and is not intuitive to use at all, as parameters passed to the resolve-method remain unused.

A possible fix may be not to treat empty values as any type in Spring.Container.CreationContext.TCreationContext.AddArgument:

function TCreationContext.AddArgument(const argument: TValue): Integer;
begin
  fLock.BeginWrite;
  try
    if argument.IsType<TTypedValue>(False) then
      Result := fTypedArguments.Add(argument)
    else if argument.IsType<TNamedValue>(False) then
      Result := fNamedArguments.Add(argument)
    else
      Result := fArguments.Add(argument);
  finally
    fLock.EndWrite
  end;
end;

Thank you!

Daniel

Comments (1)

  1. Log in to comment