Robert Westerlund

A developer's blog on code, technology and tools in the Web, .NET and other development areas.

NAVIGATION - SEARCH

"GetMemberName" or "getting rid of (some) magic strings"

Earlier today I had another discussion() with a co-worker of mine. This discussion related to magic strings and potential ways to get rid of them. I have previously mentioned that I dislike magic strings, but I haven't mentioned why. Nor have I mentioned in which circumstances which I dislike seeing them.

When do I use magic strings

There are cases where magic strings are pretty useful. An example of this is in communicating between different applications, where strings are more descriptive than using, for example, an integer. Thus, if I send a message from application A to application B telling it to do “<action>print</action>” on something, it is a lot more descriptive and easy to debug than if it would be “<action>3</action>”. The same goes for the code listening to this message.

switch(action)
{
    case “print”:
        //Do the printing
        break;
}

it is a lot better than

switch(action)
{
    case 3:
        //Do the printing
        break;
}

However, I often try to limit the risk of errors, when using magic strings, for example by creating an XSD forcing an enumeration constraint (only allowing the content of the action element to be one of a limited set of values). This also has the benefit of making the message easier to use. (Whether it could still be called a magic string after enforcing an enumeration constraint on the value is a question of definitions, so in general I try to avoid the pitfalls of magic strings.)

When do I try to avoid magic strings

On the other hand, there are a lot of cases where I believe that magic strings are nothing but evil (although in some cases they may be necessary evil). One example of this is the INotifyPropertyChanged interface. Another such example is throwing ArgumentNullExceptions.

public class MyClass:INotifyPropertyChanged
{
    public MyClass(IRepository repository)    
    {
        if (repository == null)
        throw new ArgumentNullException(“repository”);
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
            OnNotifyPropertyChanged(“Name”);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}

What happens when we change the IRepository to be a IDataRepository and therefore also renames the constructor parameter to dataRepository? What happens when we rename the Name property to Title? Well, in most cases we will remember to change the string as well, but every now and then we will forget to change the string. Also, sometimes we will misspell the property name, e.g. writing -“Neme” instead of “Name”. Of course, I could unit test all the property setters to make sure that the NotifyPropertyChanged is fired with the correct propertyName. While this might be a good (or bad) idea in and of itself, we still would have to remember to change the contents of the string in the unit test when we rename the property.

Expressions to the rescue

With C# 3.0 we got lambda expressions, which I am very fond of. Our nice lambda expressions are a lot better as a syntax for writing anonymous methods than what anonymous delegates ever were. The sometimes well-known secret here, however, is that the same lambda expression code could mean two completely different things, depending on the context. Given the following code:

DoStuff<string>(stringValue => Console.WriteLine(stringValue));

We would pass completely different things to our DoStuff-method depending on how that method is defined (Which could be compared to sending a constant integer 1 as a parameter to method. If the method takes an integer, the parameter would be compiled as an integer but if the parameter is defined as a double, the compiler would help us and change the 1 to a double with the value 1.0d). If the parameter is defined as an Action<string>, then we would receive a precompiled Action which we could use. If, on the other hand, the parameter is defined as Expression<Action<string>> then we would instead get an expression tree. Using this expression tree, we could compile and execute it if we want to, but we also have the possibility to examine the expression tree (which is very useful, for example when creating an IQueryable or IQbservable).

The GetMemberName-method

What I would want in the above examples is that if I would rename the property or parameter using the refactoring tools in Visual Studio, the string would automatically be updated as well. And if I, for some reason, would have misspelled or forgot to update the string, I would like a compiler error. The GetMemberName-method will help us achieve this goal.

public static class ObjectExtensions
{
    public static string GetMemberName<T, K>(this T obj, Expression<Func<T, K>> expression)
    {
        if (expression == null)
            obj.GetMemberName(_ => expression);
        MemberExpression memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
            throw new ArgumentException("Expression of type " 
                + expression.Body.Type.ToString() 
                + " is not supported by the GetMemberName method."
                + " Only MemberExpressions are currently supported.", obj.GetMemberName(_ => expression));
        return memberExpression.Member.Name;
    }
}

We could then change our code above to something similar to the following:

public class MyClass:INotifyPropertyChanged
{
    public MyClass(IRepository repository)    
    {
        if (repository == null)
            throw new ArgumentNullException(this.GetMemberName(_ => repository));
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
            OnNotifyPropertyChanged(this.GetMemberName(_ => Name));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}

Tiny drawbacks

Of course, for some unfortunate reason, there are no silver bullets which solve every problem, even though this one is at least silver coated. The drawback of using the GetMemberName instead of using a constant string is performance. I have performed very naive performance tests on the GetMemberName-method and it has shown that the method call took up to 30 milliseconds to perform on my laptop (which isn’t a very powerful laptop). In almost all cases I believe these milliseconds are worth getting rid of the strings, but if I would set the property 100 times per second this could be a problem (on the other hand, if I update it that frequently, perhaps it isn't a good fit for INotifyPropertyChanged). Therefore, I try to use this approach as often as I can, instead of using unnecessary magic string, and only if it would become a problem, I would consider writing the name as a string.

Unit Testing

It could be added, of course, that if you have unit tests which cover the PropertyChanged events when setting parameters this could be a non-issue, as long as you start a property rename with renaming in the tests and there renaming the string. Perhaps the GetMemberName method could be good to use in the unit test and to not use in the application code?

Creating a Custom Part Catalog for the Managed Extensibility Framework

I'm very fond of the Managed Extensibility Framework (MEF). MEF makes it very easy to create extendable and composable applications. At TechEd in Los Angeles this year Jason Olson held a presentation on opening up an application for extendability with MEF. During his session he presented a sample of a network status aware catalog, which seemed very easy to create and also felt as a very good example of a custom part catalog. Also, I haven't been able to find a good example of how to create a custom part catalog which supports recomposable imports (which is embarrasingly easy, once you know which interface to implement).Unfortunately, I haven't been able to find his code anywhere on the internet and thus decided to create a catalog inspired by his.

UPDATE:When I started writing this post (it took a while to get the focus to complete it), I couldn't find information on creating custom catalogs, but when looking again I found that an example has been created on the MEF codeplex page.

Disclaimer: All code in this post is Demo code and is supposed to be taken as such. Feel free to use the code in any manner, but always be sure you understand what copied code does and how it is done. I do not make any guarantees that code in my posts are production ready.

Introducing the Network Status Aware Catalog

The network status aware catalog is a filter catalog which makes its' decisions based on whether or not a network connection could be found. The MSDN article on the NetworkInterface.GetIsNetworkAvailable()-method (the method that the catalog will use to determine whether or not it has a network) defines a network availablility as:

"A network connection is considered to be available if any network interface is marked 'up' and is not a loopback or tunnel interface."

This does not guarantee a connection to the internet, but it is enough for our demo code.

Giving the catalog the functionality to support recomposition allows imports to state that composition containers are allowed to exchange imported parts when some state change occurs in the catalog (or the catalog for some other reason decides that it is time to perform recomposition).

The Network Status enum

Since I really hate magic strings, I will be using a simple enum to define network statuses.

public enum NetworkStatus
{
  Online,
  Offline
}

A simple enum, but beyond doubt complex enough.

Creating a filtering Part Catalog

It is very easy to create a filtering for MEF is very easy. Just inherit from the ComposablePartCatalog class and implement the abstract property called Parts. Since we want a filtering part catalog, we will also add a constructor which receives a ComposablePartCatalog as a parameter.

public class NetworkStatusAwareCatalog : ComposablePartCatalog
{
    private ComposablePartCatalog _composablePartCatalogToFilter;
    public NetworkStatusAwareCatalog(ComposablePartCatalog composablePartCatalogToFilter)
    {
        this._composablePartCatalogToFilter = composablePartCatalogToFilter;
    }

    public override IQueryable Parts
    {
        get { return _composablePartCatalogToFilter.Parts; }  
    }
}


Since the Parts property is an IQueryable, it is very easy to use link to add the filtering we want (we will be implementing the missing methods in a short while).

public override IQueryable Parts
{
    get 
    { 
        return _catalogToFilter
            .Parts
            .Where(p => !IsNetworkStatusAware(p)
                || DoesCurrentNetworkStatusMatchPartNetworkStatus(p)
            ); 
    }
}


This looks very nice so far. However, as we can see we need some way to know if a part is “network status aware” or not (that is, whether a part should only be used when the network status is either online or offline). This can be used by adding PartMetaData on Exported types. In order to understand how it would work, we here create two controls to export, one which should only be used when the network is in online status and one which should only be used in offline status (Again, I really dislike the magic string here, but as Demo code the strings here actually make the code in the post shorter and we will thus use it anyway).

[Export("NetworkStatusAwareControl", typeof(UIElement))]
[PartMetadata("NetworkStatus", NetworkStatus.Online)]
public partial class ControlWhichShouldOnlyBeUsedWhenNetworkIsOnline : UserControl
{
    //The content of this UserControl is not interesting in this post and has thus been omitted.
}

[Export("NetworkStatusAwareControl", typeof(UIElement))]
[PartMetadata("NetworkStatus", NetworkStatus.Offline)]
public partial class ControlWhichShouldOnlyBeUsedWhenNetworkIsOffline : UserControl
{
    //The content of this UserControl is not interesting in this post and has thus been omitted.
}


Accessing this part metadata is very easy to do in the ComposablePartCatalog and thus implementing the two methods IsNetworkStatusAware and DoesCurrentNetworkStatusMatchPartNetworkStatus will now be very easy (we also add a private variable called _currentNetworkStatus which, of course, should contain the current network status).

private NetworkStatus _currentNetworkStatus = NetworkStatus.Offline;
private bool IsNetworkStatusAware(ComposablePartDefinition part)
{
    return part.Metadata.ContainsKey(MetadataKeys.NetworkStatus);
}

private bool DoesCurrentNetworkStatusMatchPartNetworkStatus(ComposablePartDefinition part)
{
    return part.Metadata["NetworkStatus"] is NetworkStatus
        && CurrentNetworkStatusMatches((NetworkStatus)part.Metadata["NetworkStatus"]);
}

private bool CurrentNetworkStatusMatches(NetworkStatus status)
{
    if (Enum.IsDefined(typeof(NetworkStatus), status))
        return status == _currentNetworkStatus;
    else
        return false;
}

So what do we have now? We have created our custom ComposablePartCatalog and it filters the available Parts (if they are “network status aware”) based on the “current” network status.

What about recomposition?

We have only two things left to support in our simple network status aware catalog. It is knowing the current network status and we also need to support recomposition. One step at a time. Lets start with supporting recomposition. As I mentioned previously, supporting recomposition is very easy when you know which interface to implement, since the interface only defines one single event; the Changed event.

We start by adding the implementation of the interface to the class definition as well as implementing the event and adding a protected OnChanged method.

public class NetworkStatusAwareCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged
{
    //The rest of the class is the same as it was previously and has been emitted.
    public event EventHandler Changed;
    protected void OnChanged()
    {
        var changedEvent = Changed;
        if (changedEvent != null)
            changedEvent(this, new ComposablePartCatalogChangedEventArgs(this.Parts));
    }
}
Only one more thing to do now; updating our "current network status" when the network status availability changes and calling the OnChanged method when things change. To our help comes the NetworkInterface class and the NetworkChange class. The NetworkInterface class has the method GetIsNetworkAvailable and the NetworkChange class has the event NetworkAvailabilityChanged (in a Silverlight test application I used the NetworkAddressChanged event instead, which seemed to work just fine for this purpose).
private void CheckNetworkStatus()
{
    var previousNetworkStatus = _currentNetworkStatus;
    if (NetworkInterface.GetIsNetworkAvailable())
        _currentNetworkStatus = NetworkStatus.Online;
    else
        _currentNetworkStatus = NetworkStatus.Offline;
    if (_networkStatus != previousNetworkStatus)
        OnChanged();
}

With this method ready, we just need to call it once initially and then every time the network availability changes (or address changes). The constructor would be a perfect place to add these calls.

public NetworkStatusAwareCatalog(ComposablePartCatalog composablePartCatalogToFilter)
{
    this._composablePartCatalogToFilter = composablePartCatalogToFilter;
    NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
    CheckNetworkStatus();
}

private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
    CheckNetworkStatus();
}

Using the network status aware catalog

Have we done all this work for nothing since we still haven’t used this catalog at all? No, of course not. Using it is extremely simple.

In my test application, which was done in Silverlight, I had ContentControl bound to a property of a custom UserControl. The property of the UserControl is a dependency property (in order to support binding, not necessary for MEF).

[Import("NetworkStatusAwareControl", typeof(UIElement), AllowRecomposition = true)]
public UIElement ChildControls
{
    get { return (UIElement)GetValue(ChildControlsProperty); }
    set { SetValue(ChildControlsProperty, value); }
}

Observe that we have specified in the attribute to the property to import using the string “NetworkStatusAwareControl” with the type UIElement (the string and type matches those of the Export) and that this is where we say AllowRecomposition = true. Creating the UserControl and allowing the container to do its composition magic is now very easy (since my application was a Silverlight application, this code is taken from the application startup event handler of the App class).

var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(new NetworkStatusAwareCatalog(catalog));
this.RootVisual = container.GetExportedObject(ExportConstants.RootVisual);