There are many tricks you can use to avoid having to depend on a specific IoC container for most of your code, the easiest of which is using constructor injection. If you are configured to use the Locator Service template, simply create your own Locator Service class, which wraps the actual core of the IoC container that you plan to use.
Thus, the point of the IoC container is to achieve “control inversion”: i.e. moving the control from the lower levels up. This means that you need to have a dot near the "top" (or "root") application that actually knows about all the service implementations that it is going to use, as well as about your specific IoC implementation. This should be limited to several classes. Typically, the “Context Root" of an application is the place where you will initialize your IoC container and Service Locator. There must be a specific module or group of modules that takes care of setting up all your bindings.
If you want to enable the use of plugins, you need to create a specific API for their use and compliance. Just letting other packages define new IoC bindings is a recipe for disaster, because you don't know how well these different packages will play together.
ASP.NET MVC 3 is a good example of this. They have specific factory locators that you override in the global Application_Start method. To implement one of these factories, you must comply with the API that they provide to you. But you can create an implementation that uses any IoC container you want, or nothing at all. You do not change the "bindings" at all. You simply tell the infrastructure that for the current application you want to use this factory to create controllers or model metadata providers instead of using the factory by default.
To use another example that is more applicable to your specific example, consider the ISearchProvider case. You may have a built-in LuceneProvider , and perhaps one of your plugins may provide GoogleProvider . Which of these suppliers do you want to use? The mere presence of GoogleProviderPlugin means LuceneProvider is no longer available? Should searches somehow combine the results of both of these providers? Should a user select one or more providers from the user interface?
Regardless of the answer to these questions, the end point is that you want your application to control this, not the plugin. Instead of giving the blanche plugin card for blanking with your DI bindings, you want to tell the plugin: "I allow you to define additional search providers, and here is how you can register them." They can be registered in various ways, including annotations / class attributes or the simple presence of a class that implements this interface. But the important point is that there is an API that specifically defines what they can “connect to” and what you need from anyone who creates the plugin.
Now, if GoogleProvider has dependencies defined in the plugin, this plugin can resolve these dependencies, but it wants to. Hopefully he will use some kind of IoC container, but if he doesn’t, then there is no skin from your back. You can still be agnostic about the container they use, if any.
If there are certain services that you expect from SearchProvider , you can enable these services or factories for these services as part of the initialization API for your plugin. Thus, your plugin can access these services without thinking about your IoC container application.