Decor.NET
Decor.NET copied to clipboard
Cannot Instantiate Object Because Parameterless Constructor is Missing
User reported an issue of being unable to create a decorated object instance without parameterless constructor.
Reproduced here:
using Decor;
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Xunit;
namespace Reproduce
{
public class DecorRepro
{
public class Dependency { }
public class Decorator : IDecorator
{
public async Task OnInvoke(Call call) => await call.Next();
}
public abstract class Base
{
protected Base(Dependency featureToggle)
{
}
public abstract Task OnMessage();
}
public class Actual : Base
{
public Actual(Dependency featureToggle) :base(featureToggle)
{
}
[Decorate(typeof(Decorator))]
public override async Task OnMessage() => await Task.Delay(1);
}
[Theory, AutoMoqData]
public void aaa(ServiceCollection serviceCollection)
{
var provider = serviceCollection
.AddDecor()
.AddTransient<Dependency>()
.AddTransient<Decorator>()
.AddScoped<Actual>().Decorated()
.BuildServiceProvider();
var sut = provider.GetService<Actual>();
}
}
}
The problem arises from the target service not having an interface with parameter-less constructor. A workaround is to just add an interface and add it to dependency container registration.
There are 3 ways to solve this from the package perspective. In an increasing difficulty they are:
- Just catch these cases early and inform that it is not supported. Provide a guide for a work around using interfaces.
- Castle's DynamicProxy would allow to create objects using dependency container (issue here).
- Identify the constructor and needed parameters in
Decorand resolve them manually usingServiceProvider. This steps a bit outside of this package's scope.
Looking at the future, Decor V3 will not depend on Castle.Core and will not have this problem.