Friday 18 April 2014

Calling generic methods with runtime Type parameters

In the normal course of events, a call to a generic method needs to have its type resolved at compile time. For example, consider this class and method:
class TypeWriter
{
    public void WriteType<T>(TextWriter target)
    {
        target.WriteLine("T is {0}"typeof(T));
    }
}
This generic method needs to be called with its type parameter resolved at runtime, like this:
var typeWriter = new TypeWriter();
typeWriter.WriteType<Program>(Console.Out);
which gives this output:


But what do you do if you only discover the types at runtime so don't know the types at compile time? This commented code wouldn't compile because the variable assemblyType can't be resolved to a generic parameter:
foreach (var assemblyType in Assembly.GetExecutingAssembly().GetTypes())
{
    // typeWriter.WriteType<assemblyType>(Console.Out);
}

This is where System.Reflection comes in. The MethodInfo class has a method MakeGenericMethod that takes an array of System.Type, substitutes the method's generic parameters for the arguments and returns a new MethodInfo instance. This new MethodInfo instance can then be invoked like any other. Here's how this looks in code:
foreach (var assemblyType in Assembly.GetExecutingAssembly().GetTypes())
{
    // Get a handle on the method to call
    var method = typeof(TypeWriter).GetMethod("WriteType");

    // Pass the type parameter(s)
    var genericMethod = method.MakeGenericMethod(assemblyType);

    // Call the method on the TypeWriter instance, passing parameter(s)
    genericMethod.Invoke(typeWriter, new[] { Console.Out });
}
This gives the output:


Thursday 3 April 2014

KeyedCollection

During a talk at DevWeek 2014 I discovered the KeyedCollection<TKey,TItem> class. The class is in the System.Collections.ObjectModel namespace, and is an alternative to the Dictionary<TKey,TValue> for items where the key is embedded in the item itself. The following code sample shows where it pays dividends to use a KeyedCollection over a Dictionary.

The following program creates a dictionary of Person objects; it uses the Id of the Person as the key, and the person itself as the value:


Bearing in mind that this is a contrived example, there is a problem with this code; having to specify the key manually has lead to a typo (didn't you spot it?):


If the key to use for your collection item can be derived from the value, the KeyedCollection allows you to do that.
The KeyedCollection class is abstract, so you need to inherit from it. Having done so, you can override the GetKeyForItem method; this is the method that the framework calls to obtain the key of the item:


Items can then be added to the collection as you would any collection, either using the Add method, or an object initialiser as I've done here:


When retrieving an item, the KeyedCollection behaves like a Dictionary rather than a List, because you access items by their key rather that their position in the collection:


See more about the KeyedCollection class on MSDN: http://msdn.microsoft.com/en-us/library/ms132438(v=vs.110).aspx

System.BitConverter Class

Every now and again a new framework class comes to my attention. At DevWeek I was attending a talk on Cryptography and an incidental part of the talk featured the BitConverter class. This is a class in the System namespace and has a bunch of static methods that convert to and from a byte array.

The ToString(byte[]) method was the one that I saw being used. It takes an array of bytes and converts each byte to its 2 character hexadecimal equivalent. This is an alternative to Base64 encoding and is arguably more human-friendly.




Other methods on the BitConverter class allow you to convert between a byte array and numerical types:

For more details, see the MSDN documentation at http://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx