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

Could not find any registered services for type #207

Open
NeoElitech opened this issue Jul 24, 2023 · 4 comments
Open

Could not find any registered services for type #207

NeoElitech opened this issue Jul 24, 2023 · 4 comments

Comments

@NeoElitech
Copy link

NeoElitech commented Jul 24, 2023

Hi @khellang,
I'm using Scrutor to decorate an open generic type but I receive the following exception.
Could not find any registered services for type 'DecoratorDemo.ICommandHandler<TCommand>
I found a similar issue. But it's fixed already.
Here is the link to the repository
I'm using .NET.4.8 and Scrutor.4.2.2

@NeoElitech
Copy link
Author

NeoElitech commented Jul 31, 2023

namespace DecoratorDemo
{
	internal class Program
	{
		static void Main(string[] args)
		{
			var container = new Container();
			var serviceProvider = new ServiceCollection()
				.AddSimpleInjector(container)
				.AddServices()
				.BuildServiceProvider()
				.UseSimpleInjector(container);

			var command = serviceProvider.GetRequiredService<ICommandHandler<FooCommand>>();
			command.Handle(new FooCommand());
		}
	}

	public static class ServiceCollectionExtensions
	{
		public static IServiceCollection AddServices(this IServiceCollection services)
		{
			// *********** Can NOT Decorate ***********
			return services
				.AddTransient(typeof(ICommandHandler<>), typeof(CommandHandler<>))
				.Decorate(typeof(ICommandHandler<>), typeof(CommandHandlerDecorator<>));

			// *********** Can Decorate ***********
			//return services
			//	.AddTransient<ICommandHandler<FooCommand>, CommandHandler<FooCommand>>()
			//	.Decorate(typeof(ICommandHandler<>), typeof(CommandHandlerDecorator<>));
		}
	}
}

@khellang
Copy link
Owner

khellang commented Sep 1, 2023

Hello @NeoElitech! 👋🏻

Sorry for the long reply time.

The issue with open generic decoration is that Scrutor needs to know which concrete services are registered ahead of time. It does this by inspecting the concrete/closed services already registered in the container. If you replace the first AddTransient call with something like

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

Scrutor will can the specified assembly and add all closed generic services that implements ICommandHandler<T>.

When you then call Decorate, it should be able to find the registrations and successfully decorate them 😄

@coding-bunny
Copy link

coding-bunny commented Sep 25, 2023

I'm running into a similar problem, and the suggested solution doesn't provide any help.
We have an assembly with an interface, a service and service decorator. They're all in the same assembly with their own extension method to register them:

    public interface IGetJoinedDocumentsService<out TDocument, in TUniqueId>
    {
        /// <summary>
        ///     Retrieves data of type <see cref="TDocument"/> related to a specified <paramref name="uniqueId"/>. 
        /// </summary>
        /// <param name="uniqueId">An instance of <see cref="TUniqueId"/> of a to retrieve related data for.</param>
        /// <param name="cancellationToken">An instance of <see cref="CancellationToken"/> to stop enumeration.</param>
        /// <returns>A collection of <see cref="TDocument"/> with data; empty collection if there are no data.</returns>
        IAsyncEnumerable<TDocument> GetAsync(TUniqueId uniqueId, CancellationToken cancellationToken);
    }


internal class GetJoinedDocumentsService<TDocument, TUniqueId> : IGetJoinedDocumentsService<TDocument, TUniqueId> {}
public class GetDocumentEnrichmentDecorator<TDocument, TUniqueId> : IGetDocument<TDocument, TUniqueId> {}

And this throws the error:

 var assembly = typeof(IGetJoinedDocumentsService<,>).Assembly;
            
            serviceCollection.Scan(scan => scan
                .FromAssemblies(assembly)
                .AddClasses(classes => classes.AssignableTo(typeof(IGetJoinedDocumentsService<,>)))
                .AsImplementedInterfaces()
                .WithTransientLifetime());
            
            return serviceCollection
                .AddScoped(typeof(IGetJoinedDocumentsService<,>), typeof(GetJoinedDocumentsService<,>))
                .Decorate(typeof(IGetJoinedDocumentsService<,>), typeof(GetJoinedDocumentsServiceEnrichmentDecorator<,>))
Scrutor.DecorationException: Could not find any registered services for type 'BizMachine.Prospector.Modules.Filtering.Enrichment.IGetJoinedDocumentsService<TDocument, TUniqueId>'.
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Decorate(IServiceCollection services, DecorationStrategy strategy)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Decorate(IServiceCollection services, Type serviceType, Type decoratorType)
   at Microsoft.Extensions.DependencyInjection.EnrichmentServiceCollectionExtensions.AddFilteringEnrichmentDecorators(IServiceCollection serviceCollection) in D:\src\bm-products-api\Modules.Filtering.Enrichment\EnrichmentServiceCollectionExtensions.cs:line 23
   at Program.<>c.<<Main>$>b__0_0(HostBuilderContext context, IServiceCollection services) in D:\src\bm-products-api\Modules.Filtering.ElasticSearch.Console\Program.cs:line 21
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at Program.<Main>$(String[] args) in D:\src\bm-products-api\Modules.Filtering.ElasticSearch.Console\Program.cs:line 12
   at Program.<Main>(String[] args)

@savornicesei
Copy link

savornicesei commented Feb 6, 2024

I believe this is caused by #39 and can't be fixed as things are today were in 2017. IT seems by this SO thread that there are ways to do it with the MS DI.

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

4 participants