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.

This entry was posted in MEF. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/members/gblock/default.aspx Glenn Block

    @wcoenen

    I am glad you think it turned out simple. I tried to keep with the intent of the last post and not introduce the need for the config provider in each test.

    Recomposition would technically be inappropriate as it reates to when an actual export changes, rather than a value change.

    On having the changed event, if that was valuable you could actually use something like RX frameworks’s IObservable or even have your own wrapper that implements INotifyPropertyChanged and throws the changed event when the value changes.

    Glenn

  • http://mindinthewater.blogspot.com/ wcoenen

    When I saw the title of this post, I thought it was going to involve a “IConfigurationProvider.Changed” event or maybe even recomposition. It’s interesting to see how simple the implementation turned out to be.