Decorated service called using different constructor than when not decorated
Found this issue when I was trying to decorate NewtonsoftJsonHubProtocol
To Reproduce
Given these classes
public interface IDecoratedService { }
public class DecoratedOptions
{
public bool Option { get; set; }
}
public class DecoratedWithOptions : IDecoratedService
{
public DecoratedWithOptions() : this(Options.Create(new DecoratedOptions()))
{ }
public DecoratedWithOptions(IOptions<DecoratedOptions> options)
{
OptionalValue = options.Value.Option;
}
public bool OptionalValue { get; }
}
When setup using
services.AddSingleton<IDecoratedService, DecoratedWithOptions>();
services.Configure<DecoratedOptions>(options => options.Option = true);
DecoratedOptions is injected from container and OptionalValue set to true.
When decorator added is added the parameterless constructor is called and OptionalValue is false.
services.Decorate<IDecoratedService, Decorator>();
I'm also running into this.
ActivatorUtilities.CreateInstance does have a concept of "better match" for constructors; however, that matching logic only compares the number of explicitly-provided arguments, not the number of constructor parameters, so it ends up taking the first one.
Meanwhile, the standard DI will consider constructors in decreasing order of number of parameters.
Not sure what the best solution is. Ideally, ActivatorUtilities would be brought into line with the standard DI. For this project, you might want to consider much more complex construction: essentially rewrite ActivatorUtilities.CreateInstance with your own implementation that chooses a constructor manually and builds a factory delegate.