Exporting dynamically changing configuration values

In my last post I discussed how to export configuration. A follow up question in the comments was “What if the values change?” Meaning the values that are exported using the approach I illustrated are static. In the real world however values often can change based on some user setting etc. A variant of the approach however allows the values to not be static. Instead of exporting a value, export a Func which returns the value. MEF offers nice support for this through method exports. For example to allow the “recently used file” config item to change over time, we can modify the Exporter to export that value as a method rather than a property.

 public class RecentlyUsedTrackerConfiguration
{
  private IConfigurationProvider _provider;
  [ImportingConstructor]
  public RecentlyUsedTrackerConfiguration(IConfigurationProvider provider)
  {
     _provider = provider;
     MaxItems = provider.GetValue<string>("recentlyUsedTracker.maxItems");
  }
  [Export("RecentlyUsedTracker.File")]
  public string GetFile() {
    return _provider.GetValue<string>("recentlyUsedTracker.maxItems");
  }
  [Export("RecentlyUsedTracker.MaxItems")]
  public int MaxItems {get;private set;}
}

Instead of exporting a property, we are now exporting  the GetFile method. Method exports are imported as delegates, thus RecentlyUsedTracker now looks like this.

 [Export]
public class RecentlyUsedTracker {
  [Import("RecentlyUsedTracker.File")]
  public Func<string> File {get;set;}
  [Import("RecnetlyUsedTracker.MaxItems")]
  public int MaxItems {get;set;}
}

Notice above we are importing a Func<string> for the File item rather than string. This gives us the hook to dynamically change File each time it is accessed. You could even go further an parameterized File if you wanted to pass in context to determine which File is returned.

It’s still easy to test

With this approach RecentlyUsedTracker is still easy to test. With lambda syntax it is pretty painless to pass in test values when the class is under test.