WCF ChannelFactory configuration outside of App.config?
Asked Answered
G

3

7

I've got a Windows Service that makes use of a plugin system. I'm using the following code in the plugin base class to provide a separate configuration per DLL (so it'll read from plugin.dll.config):

string dllPath = Assembly.GetCallingAssembly().Location;
return ConfigurationManager.OpenExeConfiguration(dllPath);

These plugins need to make calls to WCF services, so the problem I'm running into is that new ChannelFactory<>("endPointName") only looks in the hosted application's App.config for the endpoint configuration.

Is there a way to simply tell the ChannelFactory to look in another configuration file or somehow inject my Configuration object?

The only way I can think of to approach this is to manually create an EndPoint and Binding object from values read in from plugin.dll.config and pass them to one of the ChannelFactory<> overloads. This really seems like recreating the wheel though, and it could get really messy with an endPoint that makes heavy use of behavior and binding configurations. Perhaps there's a way to create EndPoint and Binding objects easily by passing it a configuration section?

Gregorio answered 18/2, 2011 at 19:56 Comment(0)
F
4

There are 2 options.

Option 1. Working with channels.

If you are working with channels directly, .NET 4.0 and .NET 4.5 has the ConfigurationChannelFactory. The example on MSDN looks like this:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "Test.config";
Configuration newConfiguration = ConfigurationManager.OpenMappedExeConfiguration(
    fileMap,
    ConfigurationUserLevel.None);

ConfigurationChannelFactory<ICalculatorChannel> factory1 = 
    new ConfigurationChannelFactory<ICalculatorChannel>(
        "endpoint1", 
        newConfiguration, 
        new EndpointAddress("http://localhost:8000/servicemodelsamples/service"));
ICalculatorChannel client1 = factory1.CreateChannel();

As pointed out by Langdon, you can use the endpoint address from the configuration file by simply passing in null, like this:

var factory1 = new ConfigurationChannelFactory<ICalculatorChannel>(
        "endpoint1", 
        newConfiguration, 
        null);
ICalculatorChannel client1 = factory1.CreateChannel();

This is discussed in the MSDN documentation.

Option 2. Working with proxies.

If you're working with code-generated proxies, you can read the config file and load a ServiceModelSectionGroup. There is a bit more work involved than simply using the ConfigurationChannelFactory but at least you can continue using the generated proxy (that under the hood uses a ChannelFactory and manages the IChannelFactory for you.

Pablo Cibraro shows a nice example of this here: Getting WCF Bindings and Behaviors from any config source

Friarbird answered 16/4, 2013 at 19:13 Comment(2)
I was disappointed at first because the ctor required you to define an EndpointAddress, which the endpoint already defines, and then I realized you can send null and it'll use the configured address. Thanks for posting!Gregorio
True. I forgot to mention that. Let me edit the response and make it clear.Friarbird
M
4

Use a separate AppDomain for each plugin. When you create the AppDomain you can specify a new configuration file.

See http://msdn.microsoft.com/en-us/library/system.appdomainsetup.configurationfile.aspx

Muscadine answered 18/2, 2011 at 20:24 Comment(0)
F
4

There are 2 options.

Option 1. Working with channels.

If you are working with channels directly, .NET 4.0 and .NET 4.5 has the ConfigurationChannelFactory. The example on MSDN looks like this:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "Test.config";
Configuration newConfiguration = ConfigurationManager.OpenMappedExeConfiguration(
    fileMap,
    ConfigurationUserLevel.None);

ConfigurationChannelFactory<ICalculatorChannel> factory1 = 
    new ConfigurationChannelFactory<ICalculatorChannel>(
        "endpoint1", 
        newConfiguration, 
        new EndpointAddress("http://localhost:8000/servicemodelsamples/service"));
ICalculatorChannel client1 = factory1.CreateChannel();

As pointed out by Langdon, you can use the endpoint address from the configuration file by simply passing in null, like this:

var factory1 = new ConfigurationChannelFactory<ICalculatorChannel>(
        "endpoint1", 
        newConfiguration, 
        null);
ICalculatorChannel client1 = factory1.CreateChannel();

This is discussed in the MSDN documentation.

Option 2. Working with proxies.

If you're working with code-generated proxies, you can read the config file and load a ServiceModelSectionGroup. There is a bit more work involved than simply using the ConfigurationChannelFactory but at least you can continue using the generated proxy (that under the hood uses a ChannelFactory and manages the IChannelFactory for you.

Pablo Cibraro shows a nice example of this here: Getting WCF Bindings and Behaviors from any config source

Friarbird answered 16/4, 2013 at 19:13 Comment(2)
I was disappointed at first because the ctor required you to define an EndpointAddress, which the endpoint already defines, and then I realized you can send null and it'll use the configured address. Thanks for posting!Gregorio
True. I forgot to mention that. Let me edit the response and make it clear.Friarbird
G
0

Here's a solution I found to my 2nd question... someone put the work in to read all the data from ServiceModelSectionGroup and create a ChannelFactory.

http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx

I'll be using Richard's solution though, as it seems much cleaner.

Gregorio answered 18/2, 2011 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.