Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
597 views
in Technique[技术] by (71.8m points)

c# - How do I see all services that a .NET IServiceProvider can provide?

This is a general question regarding .NET

I am given an instance of the IServiceProvider interface, but I have little documentation as to what might be possible to get from it. How would I find out a list of all the services it might provide?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...