Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get registered service by its concrete type instead of its interface type?

Please suppose I have the following classes and interfaces:

public class ConcreteRepository : IRepository<T>, IEntityOwner
{ }

public interface IRepository<T>
{ }

public interface IEntityOwner
{ }

public class SomeModel
{ }

and suppose I have registered the following service in my Asp.Net Core 2.0 startup class:

services.AddScoped<IRepository<SomeModel>, ConcreteRepository>();

I can get the instance of ConcreteRepository like this:

var concreteRepositoryInstance = 
         httpContext.RequestServices.GetService(typeof(IRepository<SomeModel>))
              as IRepository<SomeModel>;

How can I get the instance of ConcreteRepository by the type of ConcreteRepository?

I imagine something like this:

var concreteRepositoryInstance =  
         httpContext.RequestServices.GetService(typeof(ConcreteRepository))
              as IEntityOwner;

Please note that I cannot use any generics to answer my question, because my use case refers to a custom attribute that takes the type of concreteRepository as an input parameter (and attributes cannot be generics by design).

What I tried so far:

(a) I checked and tried all httpContext.RequestServices.GetService... methods but they all require the type of interface with which the concrete type is registered with.

(b) I was thinking about getting all services from the dependency container, but IServiceProvider does not offer getting all services. I can only get them by the type of interface.

like image 516
philipp-fx Avatar asked May 31 '18 15:05

philipp-fx


People also ask

When to use interfaces instead of concrete types?

Had a discussion that i felt i needed some external input on. Normally always use interfaces instead of concrete types (on lists, injectable services and so forth). For example in lists i just pass around IEnumerable instead on List and so forth. The same applies for custom types (ICustomClass instead on CustomClass).

How do I register a service with all its public interfaces?

AsImplementedInterfaces () // register the service with all its public interfaces . SingleInstance (); // register the services as singletons In this example, Autofac will find all concrete classes in the assembly who's name ends with "Repository", and register them in the container against any public interfaces they implement.

How does Autofac find all concrete classes in an assembly?

In this example, Autofac will find all concrete classes in the assembly who's name ends with "Repository", and register them in the container against any public interfaces they implement. So for example, given the following classes and interfaces: services. AddSingleton < IStubRepository, StubRepository > (); services.

Is it possible to return an abstract type from an interface?

In general, you want to accept as abstract a type as possible, and return as concrete a type as possible, but the situation you came across isn't really a question of abstract vs. concrete types. If you want the caller to be responsible for making sure an argument is serializable, that needs to be specified in the interface.


Video Answer


1 Answers

Try registering type directly like so

public void ConfigureServices(IServiceCollection services)
{
    // container will create the instance of this type
    services.AddScoped<ConcreteRepository>();
}

Then you will be able to resolve type directly with

var concreteRepositoryInstance =  
         httpContext.RequestServices.GetService(typeof(ConcreteRepository))
              as IEntityOwner;
like image 170
Amoenus Avatar answered Nov 14 '22 22:11

Amoenus