Under the assumptions that:
- The binding doesn't change when the address changes (e.g., it doesn't switch from HTTP to HTTPS)
- The address might change on a per-request basis
Then I'd probably solve it with a combination of lambdas and a small interface.
First, you'd want something that retrieves the address from your data store:
public interface IAddressReader
{
Uri GetAddress();
}
The implementation of that would read from the database (or environment, or XML config, or whatever).
Then I'd use that in my registrations:
builder
.RegisterType<MyDatabaseAddressReader>()
.As<IAddressReader>();
builder
.Register(c => new ChannelFactory<IService>(new BasicHttpBinding()))
.SingleInstance();
builder
.Register(c =>
{
var reader = c.Resolve<IAddressReader>();
var factory = c.Resolve<ChannelFactory<IService>();
var endpoint = new EndpointAddress(reader.GetAddress());
return factory.CreateChannel(endpoint);
})
.As<IService>()
.UseWcfSafeRelease();
That way you can just take in an IService
(or Func<IService>
) as a constructor parameter and your calling class won't know about Autofac, service location, or endpoints.
If the binding also changes, it gets a little more complicated. You probably don't want a brand new channel factory spun up for every channel, so you'd want to have some sort of caching mechanism where you:
- Get the settings from the configuration source.
- Compares those settings against the settings currently in use.
- If the settings don't match...
- Dispose of the previous channel factory.
- Create a new channel factory with the new settings.
- Cache the channel factory for later reuse.
- Return the current channel factory.
If you can use cache dependencies on the settings, all the better, but not every configuration source supports that, so YMMV. I'd probably implement a custom module for that to encapsulate the logic, but I won't write all that out here.