System.IServiceProvider
has a single method, .GetService(Type)
, which returns a single service. It's essentially a dictionary mapping types to services, and it does not provide access to all keys, probably because it's intended for implementation over the wire.
It's up to the class implementing the interface to expose a method or property that allows discovery of the services it provides - there is no general way to see all provided services using the interface alone.
Solutions:
If you have control over the service providers' source, make a child interface that allows what you want
interface IBetterServiceProvider : System.IServiceProvider
{
IList<object> GetAllServices();
IList<Type> GetAllServicedTypes();
}
and make your services implement it.
If you don't have control over the service providers' source, either cast to the IServiceProvider
implementation type, or use reflection to look for properties or methods that tell you what you want. If there appears to be a consistent .GetServices()
sort of method in the providers you're working with, then you can use dynamic dispatch 1, 2, 3 to access that method without casting.
That said, even Microsoft's own implementations of the class are a bit of a rabbit hole. To quote the docs,
The IServiceProvider
interface is implemented by a number of types, including System.Web.HttpContext
, System.ComponentModel.LicenseContext
, System.ComponentModel.MarshalByValueComponent
, and System.ComponentModel.Design.ServiceContainer
.
HttpContext
implements the interface, but the GetService(Type)
method is documented as internal use only, and the only service it contains (in the public API, at least) is PageInstrumentation
. There is no way to query for all services in this implementation.
ServiceContainer
doesn't actually implement the interface (though it does have an internal field of that interface type.) Even though the ServiceContainer
doesn't implement the interface, it
does implement the method, and it's a bit scary. It does confirm suspicions - it's a glorified dictionary mapping types to services. Again, this implementation doesn't provide its own way of getting all services it holds. This is the one I expected to, since it's explicitly a container of services.
LicenseContext.GetService(Type)
just returns null unless its overridden. Perhaps some of this class' subclasses provide a way to get all services, but this one doesn't.
I'm done digging through source and docs. It appears a bit messy, but the short answer above holds: old name or new, pseudoimplementation or actual implementation: there is no way to get all services from the IServiceProvider
interface alone, and none of Microsoft's implementations that I found give you a way to do that either.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…