Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Methods for composing configuration for composite applications (eg PRISM, MEF)

Frameworks such as PRISM and MEF make it very easy to design complex applications out of multiple, composable components. One common example of this is a plug-in architecture where an application shell can be dymanically reconfigured with plug-in UI components (eg by dropping DLLs into a Plug-ins directory).

This is all well and good, but as Vaccano spotted in Can Prism be modular when calling webservices? there are circumstances where each individual plug-in requires its own set of configuration - WCF bindings being a typical example, but there are many other scenarios (logging, database connections, etc.) with similar needs.

So, as I see it, the options we have are:

  • All config goes into the App.config of the shell application (which as Vaccano mentioned breaks the whole encapsulation & deployment advantages of this model), or
  • Each plug-in assembly uses a bespoke mechanism for config (eg an embedded resource) and then uses this to dynamically configure a WCF service, for example (which at best is messy and time consuming, and at worst may not be possible)

Neither of these options are ideal, but they are workarounds. However, the ideal situation would be for each plug-in DLL to have either self contained config (such as an embedded resource file) or an Xxx.dll.config file, and have each of these XML config fragments merged into the App.config configuration of the shell application dynamically at runtime. This is reminiscent of the way Machine.config and App.config files are merged.

My question, therefore, is: has anyone come across any existing frameworks or techniques which could be used to allow this dynamic merging of composite config files into the in-process configuration of the container application? I am surprised not to see this as part of PRISM or MEF and therefore slightly wary of posting this question in case I have missed something obvious - if so, please just quietly post the relevant link :)

like image 830
Chris Ballard Avatar asked Apr 01 '11 13:04

Chris Ballard


1 Answers

We've run up against the same problem. I've not found a solution to this either.

Here's two things I've seen people do (or we've done):

Manual Service Endpoint Registration

Create an application service registry that says how to make a ChannelFactory from a T. Each Module can contribute to this in IModule Initialize by calling RegisterService<T> and all subordinate views of that Module can get their Channel Factories from it:

public interface IServiceRegistry
{
     void RegisterService<T>(ServiceEndpoint ep);
     ChannelFactory<T> GetService<T>();
}

Instead of returning ChannelFactory<T> here you could just return T of course (caveat emptor). View/ViewModels would simply ask for an IServiceRegistry as a dependency and grab their service proxies this way. This also provides a convenient place for isolation when writing unit tests.

Embedded Config

A system of conventions roughly doing the same thing as above, but based on config embedded in the DLL (as you suggested) and utilizing named configurations. You'd consume this in the same way as above, but it would be a slightly different experience. We use the convention "Endpoints.config" embedded in our DLL and read from that.

public interface IServiceChannelFactoryFactory //I'm terrible at naming
{
    //This is much like the generated concrete class when you use "Add Service Reference"
    //Except there is no method with an empty parameter
    ChannelFactory<T> GetService<T>(string endpointName);
}

Our "Endpoints.config" has multiple endpoints per endpointName with attributes added that make that endpoint unique for the environment (DEV, QA, Staging, Production). I don't know if this is a concern for you, but it was a convenient place to put this kind of config.

Both work. It's surprising to me that I've not seen more people talk about this. Great question.

like image 124
Anderson Imes Avatar answered Oct 22 '22 17:10

Anderson Imes