Decor.NET icon indicating copy to clipboard operation
Decor.NET copied to clipboard

Cannot Instantiate Object Because Parameterless Constructor is Missing

Open lawrence-laz opened this issue 5 years ago • 1 comments

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>();
        }
    }
}

lawrence-laz avatar Jul 27 '20 13:07 lawrence-laz

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:

  1. Just catch these cases early and inform that it is not supported. Provide a guide for a work around using interfaces.
  2. Castle's DynamicProxy would allow to create objects using dependency container (issue here).
  3. Identify the constructor and needed parameters in Decor and resolve them manually using ServiceProvider. 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.

lawrence-laz avatar Jul 27 '20 18:07 lawrence-laz