58

I am using .NET Core dependency injection, but when I am trying to get the service in another class, I am getting the 'IServiceProvider.GetService(Type)' cannot be used with type arguments' error.

What does this error means? I understand that a generic type argument is something like this: GenericInterface<>, and the GetService method does not take the GenericInterface<> as an argument.

Why am I getting this error and how do I solve it?

The interface

public interface IService
{
   void Process();
}

The class implementing the interface

public class Service : BaseService<IConfig, SomType>
{
    public Service(
        ILogger logger : base(logger)
    {
    }

    ...
}

The BaseService class is an abstract class and it implements the IService interface.

public abstract class BaseService<TConfig, TE> : AnotherBaseService, IService where TConfig : IConfig where TE : struct, IConvertible
{
      protected BaseService(ILogger logger): base(logger)
      {
      } 

      ...
}

The AnotherBaseService

public abstract class BaseService
{
   protected readonly ILogger Logger;

   protected BaseService(ILogger logger)
   {
      Logger = logger;
   }

   ...
}

How I registered them.

serviceCollection.AddScoped<IService, Service>();

How I am getting the service I need.

var incoming = serviceProvider.GetService<IService>();

NB: I am just getting started with dependency injection, .NET Core and do not know everything about DI just yet. Your answers would be of great help.

57913
  • 783
  • 1
  • 6
  • 13

4 Answers4

190

The generic GetService< T> method is an extension method. This means you need to have a :

using Microsoft.Extensions.DependencyInjection;

to allow the compiler to find it.

This method is only meant for optional services. It will return null if the object can't be constructed, either because the type wasn't registered or because some of its dependencies are missing.

GetRequiredService should be used when an application can't work unless a service is available. If an instance can't be created, it will throw an InvalidOperationException.

When that exception is thrown, the full exception text will be a huge help in finding the actual problem. Exceptions thrown in constructors can appear in the Exception.InnerException property. The sequence of calls that ended up in an exception being thrown will appear in the StackTrace property. Calling Exception.ToString() will return a string that contains all of that information for the current exception and any inner exceptions.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • It worked, but I am now having a null exception. Can you please help? – 57913 Jan 16 '19 at 12:54
  • @Cookie this means that the type wasn't registered or couldn't be constructed. Use `GetRequiredService< T>` if your application can't work with a specific service. If the service registration is missing GetRequiredService will throw an exception explaining the reason. Sometimes it's clear (a service wasn't registered or a constructor threw), sometimes not – Panagiotis Kanavos Jan 16 '19 at 13:00
  • @Cookie to help with your specific case you'll have to post code that reproduces the issue. If you try `GetRequiredService` post the full exception text, as returned by `Exception.ToString()` – Panagiotis Kanavos Jan 16 '19 at 13:02
  • Thank you for your quick reply @Panagiotis Kanavos. I found the cause of it, the null exception occurs because a service that is being used by the "Service" has not been registered. – 57913 Jan 16 '19 at 13:07
  • 1
    This worked, thanks. For some reason intellisense wasn't giving me the hint – cesarmart Jan 17 '20 at 21:43
  • Doesnt work for me. – Frank Sep 22 '21 at 13:10
  • @Frank `doesnt work for me` isn't very clear. That method is used by every .NET Core developer in one form or another – Panagiotis Kanavos Sep 22 '21 at 13:14
7

It means your compiler only has knowledge of the method that takes a type.

You could call

var incoming = serviceProvider.GetService(typeof(IService));

or you could add a

using Microsoft.Extensions.DependencyInjection;

to make sure your compiler knows the extension method that lets you specify your type as a generic parameter. This might need the package Microsoft.Extensions.DependencyInjection.Abstractions to be installed.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • 1
    I was starting to write the *exact* same answer, but you were faster :-) – Jcl Jan 16 '19 at 12:26
  • @nvoigt Thank you, this worked, I am now having a null exception error where I getting the service. Do you know what could be causing it? – 57913 Jan 16 '19 at 12:37
  • Doesnt work for me.\ – Frank Sep 22 '21 at 13:10
  • @Frank Please open a new question with *details* what exactly is not working in your context. I'm afraid I can do nothing about a comment that says "Doesn't work for me" without knowing any context. – nvoigt Sep 22 '21 at 13:12
4

The short answer which is very well explained in the above posts:

ServiceProvider.GetService<T>(); 

with the use of following namespace which needs to be defined explicitly rather than relying on intellisense

using Microsoft.Extensions.DependencyInjection;

Also Keep a note there can be mutiple problems if you getting null exception after this:

  1. In startup make sure Hostbuilder service is set to ServiceProvider value

    ServiceProvider = host.Services;

  2. Other could be the constructor of the T class couldn't resolve the dependency of the Interface being used.

**

Thanks ! Happy Coding :)

**

hemant
  • 321
  • 2
  • 5
0

you should use

var incoming = serviceProvider.GetService(typeof(IService));
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103