I finally managed to build a working solution of a plugin architecture with help of some guys over here, but now a new problem arises.
My hosting application uses it\'s
I'm a colleague of Erik. Since he'll be on a well deserved holiday the next few weeks I'll elaborate a bit more on this issue.
In our plugins, we use multiple instances of WCF service clients. The neat thing of these services is that they come with app.config sections which you can use to configure the behavior, servicetype, security, etc. etc.
Now when we load our plugins, these sections are missing from config and therefore the correct endpoints can't be found. Of course we could set them in code, but that kind of whacks the ability to set other config options along the way when needed. We might want to implement ws-security for instance.
So we need a way to load these configs so the plugins can read there respective settings. We could of course merge all configs into one, but that kind of eliminates the "just plugin" method since you would have to manage configs alongside the plugin installation.
I thought about creating a little tool which would merge the 'master' config with all configs placed in a subdir of the project and replace the .exe.config file with that one. I think that would work, but I was wondering if .NET doesn't provide better options. Multiple AppDomains isn't a thing which would work because the plugins have to interact (provider/consumer model) with each other and we don't want to switch to remoting just because of this issue.
Update: I fixed most issues by using the ConfigurationManager to open existing configs for reading appSettings. As for the WCF clients; you can load endpoint/binding configuration for server and client as found here: http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx
You're working against the architecture of app.config. You get one app.config file per executable (EXE, not DLL). The executable launches, creates its AppDomain, and then loads MyApp.exe.config. You can add app.config objects all you want in Visual Studio, but they are ignored for DLLs. I think what you want to do is manually copy the XML from the dll.config and paste it into the application level app.config. (I'm sure there's a way to automate this using TeamBuild or some such.) The overridden values will then be available to your Properties.Settings class.
I usually prefer to avoid the whole app.config mess by creating a dedicated Xml file that the host processes with the plugin's settings also inside. The Xml would look something like this:
<root>
<Settings>
Here's where anything specific to the app goes.
</Settings>
<plugins>
<plugin type="mylibrary.myclass">
Here I let the plugin serialize itself however it wants to.
</plugin>
</plugins>
</root>
The hosting app then creates the plugin from the type attribute and tests if the class implements ISerializable; if it does, then the plugin will deserialize itself. It's a bit scary to have the plugins inline with the app's settings, but if you load the plugin's substring of Xml into a new XmlReader then you don't have to worry about an error in the plugin from reading too far in the Xml string.
Would something like ConfigurationManager.OpenMappedExeConfiguration help here? You can create a Configuration object reading in the values from a specific file.
I prefer to build and use an IConfigManager type plugin. It job is to abstract how the configuration is stored. You receive an instance of it through dependency injection. This way, the IConfigManager implementation can load settings from multiple .config files, from the network, a db or any other source. I also use it to provide default values based on user, machine and/or application - which can be overridden by the user e.g. background colour, font etc.
Other advantages to this method are that settings can be persisted in a consistent way across all plugins - without the plugins having to care, the place where your plugin stores its settings can change transparently (from .config to other) and lastly, the IConfigManager can be mocked during unit testing to simulate different situations.
I hope that helps.
You could make the each plug in read it's own ConfigurationSection then in the main config file use the ConfigSource setting to point to an external file. (See this link for more information)
You don't fully escape having plugin config information in the main app.config file but at least the plugin specific settings are in separate files.