Project Description

Feber is a library that developers can use to vastly improve the performance of common reflection-based code.
Feber is developed in C# 4.0 and depends heavily on lambdas and expressions, but most of it is abstracted away from the users of the library.

It is quite common to use reflection to iterate over a set of properties and perform some action on an instance of the code.

For example, here is code that copies scalar property values from the source object to the destination:

internal static T Map<T>(T source, T destination) where T : class
{
    foreach (var pi in typeof (T).GetProperties())
    {
        pi.SetValue(destination,
                    pi.GetValue(source, BindingFlags.GetProperty | BindingFlags.Instance, null, null, null),
                    BindingFlags.SetProperty | BindingFlags.Instance,
                    null,
                    null,
                    null);
    }
    return destination;
}

Usually, this code is written to simplify the maintenance of explicitly hand-written assignments, such as:

    destination.Id = source.Id;
    destination.Name = source.Name;
    destination.DateAndTimeOfBirth = source.DateAndTimeOfBirth;
    destination.BirthWeightInKilograms = source.BirthWeightInKilograms;
    destination.IsMultipleBirth = source.IsMultipleBirth;
    destination.BirthOrder = source.BirthOrder;
    ...

The hand-written code is high-performance but high-maintenance. The reflective code is low-maintenance but also low-performance. If there are a lot of objects being copied (say in an ORM implementation),  the reflection-based approach may be prohibitively expensive.

What we really want is a high-performance, low-maintenance approach.

If Only…

Imagine a mechanism by which we could generate a set of lambda actions, one for each property, which each copy over the value of that property from the source to the destination.

Something like:

(T _source, T _destination) =>
    {
        _destination.Id = _source.Id;
        _destination.Name = _source.Name;
        ...
    }

And now imagine that we cached this function somewhere, and every time the copy operation was required, we would simply apply this lambda to the two objects we want to process.

This imaginary system would be low-maintenance because the lambdas are created automatically – just like reflection, in fact – and high-performance, since the copy operation actually only applies a pre-computed lambda.

Enter Feber

The Feber library is such a system. It consists of a few functions which can generate these complex lambda sets for each property in a property-set.

The strength of the Feber library is its flexibility. It can generate composite lambda-sets for any user-defined operation, so one can generate object copiers, comparators, mappers and serializers, fully dynamically, with almost no loss of performance when compared with explicit coding.

Furthermore, the Feber library is fully capable of supporting dynamic object types and can automate the property-access and property-change operations natively. This means that any generated class can be used with dynamic object arguments with a minimum of coding overhead.

Here is how we can use the Feber library to implement the object copier described above:

public static class FastCopier<T>
{
    private static readonly Action<T, T> _copy =
        typeof (T).BuildCompositeAction<T, T>(
            (_pi, _srcParam, _destParam) => Expression.Assign(Expression.Property(_destParam, _pi), Expression.Property(_srcParam, _pi)));

    public static void Copy(T source, T destination)
    {
        _copy(source, destination);
    }
}

Neat, eh?

Welcome!

Explore, Enjoy and Employ Feber freely in your code. Let me know how it goes!

Last edited Jul 10, 2011 at 11:23 AM by johnazariah, version 6