Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorator registration fails with 5.0.1 and works with 4.1.0 #231

Open
markuspalme opened this issue Sep 30, 2024 · 2 comments
Open

Decorator registration fails with 5.0.1 and works with 4.1.0 #231

markuspalme opened this issue Sep 30, 2024 · 2 comments

Comments

@markuspalme
Copy link

markuspalme commented Sep 30, 2024

This open generics registration worked with 4.1.0:

foreach (var serviceType in typeof(ICommandHandler<>).Assembly.GetTypes())
{
    if (serviceType.IsAbstract || serviceType.IsInterface || serviceType.BaseType == null)
    {
        continue;
    }

    foreach (var interfaceType in serviceType.GetInterfaces())
    {
        if (interfaceType.IsGenericType && typeof(ICommandHandler<>).IsAssignableFrom(interfaceType.GetGenericTypeDefinition()))
        {
            serviceCollection.AddScoped(interfaceType, serviceType);
            break;
        }
    }
}

serviceCollection.Decorate(typeof(ICommandHandler<>), typeof(CommandLoggingDecorator<>));

With any of the 4.2.x releases (after the big decoration PR) I'm seeing this exception:

System.ArgumentException: Cannot instantiate implementation type 'My.CommandLoggingDecorator`1[TCommand]' for service type 'Type: ICommandHandler`1+Decorated'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.Populate()
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
   at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
   at Program.<Main>$(String[] args) in Program.cs:line 125

Now I've tried my luck again with 5.0.1 but am getting this exception:

Unhandled exception. System.ArgumentException: Type My.ICommandHandler`1[TCommand] contains generic parameters (Parameter 'type')
   at System.Dynamic.Utils.TypeUtils.ValidateType(Type type, String paramName, Int32 index)
   at System.Dynamic.Utils.TypeUtils.ValidateType(Type type, String paramName, Boolean allowByRef, Boolean allowPointer)
   at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.BuildFactoryExpression(ConstructorInfo constructor, Nullable`1[] parameterMap, Expression serviceProvider, Expression factoryArgumentArray)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactoryInternal(Type instanceType, Type[] argumentTypes, ParameterExpression& provider, ParameterExpression& argumentArray, Expression& factoryExpressionBody)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory(Type instanceType, Type[] argumentTypes)
   at Scrutor.DecorationStrategy.TypeDecorator(Type serviceType, String serviceKey, Type decoratorType)
   at Scrutor.OpenGenericDecorationStrategy.CreateDecorator(Type serviceType, String serviceKey)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.TryDecorate(IServiceCollection services, DecorationStrategy strategy)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Decorate(IServiceCollection services, DecorationStrategy strategy)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Decorate(IServiceCollection services, Type serviceType, Type decoratorType)
   at My.RegisterCommandHandlers(IServiceCollection serviceCollection)
   at Program.<Main>$(String[] args) in Program.cs:line 123

Is this scenario no longer supported?

If helpful I can provide a self-contained example.

@markuspalme markuspalme changed the title Decorator registration fails with 5.0.1 and works Decorator registration fails with 5.0.1 and works with 4.1.0 Sep 30, 2024
@markuspalme
Copy link
Author

markuspalme commented Sep 30, 2024

I managed to get this working again by using this (much more concise) piece of code:

builder.Services.Scan(scan => scan
    .FromAssemblyOf<SomeTypeInTheRightAssembly>()
    .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)))
    .AsImplementedInterfaces()
    .WithTransientLifetime());

builder.Services.Decorate(typeof(ICommandHandler<>), typeof(CommandLoggingDecorator<>));

But I decided to keep the issue open because it shows a breaking change nevertheless.

@khellang
Copy link
Owner

Hmm. I'm not sure whats going on there. It seems like maybe it's registering a generic type without all the geric type arguments?

Anyway, your second working code is what I'd call idiomatic registration code using Scrutor, so if it works, that's good 🤪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants