Notes from Daily Encounters with Technology RSS 2.0
 
# Sunday, July 24, 2011

Reflection is a great tool for calling methods on objects when their types are not known at compile time. Unfortunately the Type.GetMethod method doesn’t work with generic methods therefore we seem to be stuck with finding the right method by iterating through all the methods returned by Type.GetMethods:

public static MethodInfo GetMethodWithLinq(this Type staticType, string methodName, params Type[] paramTypes)
{
    var methods = from method in staticType.GetMethods()
                  where method.Name == methodName
                        && method.GetParameters()
                                  .Select(parameter => parameter.ParameterType)
                                  .Select(type => type.IsGenericType ? type.GetGenericTypeDefinition() : type)
                                  .SequenceEqual(paramTypes)
                  select method;
    try
    {
        return methods.SingleOrDefault();
    }
    catch (InvalidOperationException)
    {
        throw new AmbiguousMatchException();
    }
}

Searching for alternatives I stumbled upon a solution using expression trees posted by Neil Whitaker on StackOverflow:

private static MethodInfo GetMethodWithExpressions(Type innerType)
{
    var method = typeof(Program).GetMethod("GetSingleOrDefaultMethod", 
                                           BindingFlags.Static | BindingFlags.NonPublic, 
                                           null, Type.EmptyTypes, null)
                                .MakeGenericMethod(innerType);
    return method.Invoke(null, new object[] { }) as MethodInfo;
}

private static MethodInfo GetSingleOrDefaultMethod<TSource>()
{
    Expression<Func<TSource, bool>> fakePredicate = i => true;
    Expression<Func<IQueryable<TSource>, TSource>> lambda = l => l.SingleOrDefault(fakePredicate);

    return (lambda.Body as MethodCallExpression).Method;
}

Sure, it is more difficult to comprehend and a lot less flexible, requiring a helper method building the expression tree for every method to be returned as MethodInfo. It got me wondering though, which of the two solutions actually performs better. Let’s try them out:

static void Main(string[] args)
{
    MethodInfo method;
    Type innerType = typeof(string);

    int count = 10000;
    Stopwatch stopwatch = new Stopwatch();

    stopwatch.Restart();
    for (int i = 0; i < count; i++)
    {
        method = typeof(Queryable).GetMethodWithLinq("SingleOrDefault", typeof(IQueryable<>), typeof(Expression<>))
                                  .MakeGenericMethod(innerType);
    }
    stopwatch.Stop();
    Console.WriteLine(String.Format("Method 1: {0}", stopwatch.ElapsedMilliseconds));

    stopwatch.Restart();
    for (int i = 0; i < count; i++)
    {
        method = GetMethodWithExpressions(innerType);
    }
    stopwatch.Stop();
    Console.WriteLine(String.Format("Method 2: {0}", stopwatch.ElapsedMilliseconds));

    Console.ReadLine();
}

And the results?

Method 1: 224
Method 2: 396

Not only is the Type.GetMethods based approach simpler, it also consistently performs a lot better. We’ll just stick with it until support for generic methods is added to Type.GetMethod.

Sunday, July 24, 2011 10:31:43 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | C#
# Sunday, June 12, 2011

XmlSerializer is often a great choice for persisting objects or transmitting them over the wire, either by using default object serialization tailored only with attributes or by implementing the IXmlSerializable interface yourself. If you’re not careful though, this might come at a significant performance cost.

You’re probably already aware that in order to increase performance of XML serialization, assemblies are dynamically generated each time XmlSerializer is instantiated for the first time for a specific type. Since it happens only once in the application lifetime, it usually doesn’t pose much of a problem.

What you might not know, is that this is not necessary a once in a lifetime process. If you’re using the wrong constructor, it can happen every time you instantiate XmlSerializer. To be fair, this is mentioned in the documentation, but if you’re like me, you might not read it until you encounter performance issues in your project. So unless you’re calling XmlSerializer(Type) or XmlSerializer(Type, String), the dynamically generated assemblies are not reused. When you think about it, it also makes perfect sense. All other constructors modify the behavior of the serializer, thus causing small differences in the generated serializers and hindering their reuse.

Fortunately there is a way to avoid this performance hit. Since XmlSerializer is one of the few thread safe classes in the framework you really only need a single instance of each serializer even in a multithreaded application. The only thing left for you to do, is to devise a way to always retrieve the same instance. If you know in advance which serializers you’ll need, you can simply store them in static fields. If you don’t, you’ll need to store them in a dictionary, keyed by the arguments used in the constructor.

Your best choice for the data structure is ConcurrentDictionary introduced in .NET 4 which takes care of synchronizing for multithreading. This makes the implementation really simple:

private static ConcurrentDictionary<Type, XmlSerializer> serializers = 
    new ConcurrentDictionary<Type, XmlSerializer>();

private XmlSerializer GetSerializer(Type type)
{
    return serializers.GetOrAdd(type, t => 
        { return new XmlSerializer(t, new XmlRootAttribute("Value")); });
}

If you’re wondering what kind of performance hit I’m talking about, try running the following sample:

static void Main(string[] args)
{
    StringWriter writer = new StringWriter();
    XmlTextWriter xmlWriter = new XmlTextWriter(writer);
    xmlWriter.WriteStartDocument();
    xmlWriter.WriteStartElement("Root");
    Stopwatch stopwatch = new Stopwatch();
    int iterations = 100;

    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(string));
        serializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with XmlSerializer(string):                   {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(string), new XmlRootAttribute("Type"));
        serializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with XmlSerializer(string, XmlRootAttribute): {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    XmlSerializer staticSerializer = new XmlSerializer(typeof(string), new XmlRootAttribute("Type"));
    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        staticSerializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with a static serializer:                     {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    Console.ReadKey();
}

In my case the output was as follows:

100 serializations with XmlSerializer(string):                       2 ms
100 serializations with XmlSerializer(string, XmlRootAttribute): 17460 ms
100 serializations with a static serializer:                         2 ms

Quite a difference, isn’t it?

Sunday, June 12, 2011 4:55:48 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET
# Wednesday, June 08, 2011

One of the features introduced in Entity Framework 4 was support for foreign key properties in entity types. No matter what your opinion is about having foreign keys exposed by an ORM, there are some cases where it might be more practical or even more performant to use foreign key properties instead of navigation properties (e.g. when you are creating a new object with a reference for which you know the primary key value but don’t have a corresponding object in your ObjectContext). That’s the reason why it’s usually recommended to include foreign key columns in your model even though it will pollute your entity types with properties you might not need at all.

Update Wizard

But what if you decided not to include them in your model when you originally created it, but want to add them at a later time? Although the checkbox is enabled in the model Update Wizard which opens up when you want to Update Model from Database, its value only effects newly created entity types, but leaves existing entity types unchanged. Unless you feel comfortable deleting existing entity types and recreating them from database, you’ll have to add the properties by hand. Once you know how to do it, it’s just a matter of following a few simple steps. I’ll describe them on a simple example from Northwind database. I’ve only included three entity types: Category, Product and Supplier. We want to add CategoryID and SupplierID properties to the Product entity type.

Model without Foreign Key Properties

First add a new scalar property to the entity type:

  1. Right click on the Product entity type.
  2. Click on the Add > Scalar Property from the context menu.
  3. Click on the newly created Property and set its properties: Name to CategoryID, Nullable to True and Type to Int32.

CategoryID Properties Window

Next you need to map the database column to your new property:

  1. Open Mapping Details for Product entity type.
  2. Select the CategoryID : Int32 as Value / Property for the CategoryID : int column.

Product Mapping Details Window

Now it’s time to set up the referential constraint:

  1. Select the FK_Products_Categories association in the Model Browser.
  2. Open the Referential Constraint editor from its properties window.
  3. Select Category as Principal and CategoryID as Dependent Property.

Referential Constraint Editor

Only one step left, deleting the mapping of foreign key to the navigation property which is not allowed when you have a foreign key property in your entity type:

  1. Select the Category property of the Product entity type.
  2. Click on the Delete mappings link displayed in the Mapping Details window.

Category Mapping Details

You have to repeat the above steps for the SupplierID property and you have created a functionally identical model to the one automatically generated for you if you had selected to include foreign keys in the model before adding the tables to it.

Model with Foreign Key Properties

The above process is not only useful when you change your mind about the foreign key properties at a later time. You can also intentionally decide to add the foreign key properties only when you actually need them and avoid having redundant properties at the cost of the consistency of the model.

Wednesday, June 08, 2011 9:43:08 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | EF4
# Saturday, May 28, 2011

This week the annual Microsoft conference NT konferenca 2011 was taking place in Portorož. On Tuesday I had a talk there about the Windows API Code Pack. As promised, you can find the slides from this talk on SlideShare.

You can also download the sources for the sample project which is a working WPF MVVM image viewer application demonstrating the implementation of:

Saturday, May 28, 2011 12:03:33 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | Interop | WPF | Downloads | Presentations | Sources
# Wednesday, March 23, 2011

It seems that no matter how much experience one has with .NET framework, there are still surprises awaiting him somewhere down the road. This time I’d like to point out an interesting behaviour of MethodInfo.Invoke many of you might not be aware of. I certainly wasn’t, until today.

Since this is well documented, I should start with a quote from the documentation for the parameters parameter: “An argument list for the invoked method or constructor. […] Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type.”

What exactly does this mean? If you pass a null as a value for a value-type parameter, the call won’t fail as you might have expected. Instead, the default value for that type will be set as the parameter value.

The following short sample demonstrates this behaviour:

public void WriteValue(int value)
{
    Console.WriteLine("value = {0}", value);
}

public static void Main(string[] args)
{
    // this will result in a compile error:
    // Argument 1: cannot convert from '<null>' to 'int'
    WriteValue(null);

    // this will output:
    // value = 0
    Type type = typeof(Program);
    MethodInfo method = type.GetMethod("WriteValue");
    method.Invoke(new Program(), new object[] { null });

    // this will throw a RuntimeBindingException:
    // The best overloaded method match for 'Program.WriteValue(int)' has some invalid arguments
    dynamic obj = new Program();
    obj.WriteValue(null);
}

Obviously calling the method directly with a null value won’t even compile (unless you change the parameter type to Nullable<int>). The Reflection based call succeeds by passing the default value (0 for int) as the parameter value. The dynamic type doesn’t exhibit this behaviour – the call fails with a runtime exception.

Wednesday, March 23, 2011 9:21:12 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET
Sponsored Ads

About Me
Currently Reading

Entity Framework 4.1: Expert's Cookbook

Twitter
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2012, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.