Showing posts with label ExpressionTrees. Show all posts
Showing posts with label ExpressionTrees. Show all posts

Friday, December 23, 2011

LINQ presentation

Today I gave my old (from 2009) presentation about the LINQ. The video can be found here, slides and all code samples presented during this talk can be downloaded from here. I hope you find it useful.

Monday, October 25, 2010

Debugging Reactive Framework (RxDebugger) and Linq to objects (LinqDebugger)

[New version (2011.05.06)]

[Project download has been upgraded to the newest version of Rx (Build v1.0.2787.0) and VS2010 ] download
(Changes: projects converted to VS2010, sample project for RxDebugger added)

In this post I will present two projects LinqDebugger and RxDebugger. Few months ago after reading Bart De Smet’s great post about tracing execution of the Linq to objects queries I was wondering if it was be possible to implement the same concept but in more general way. If we want to trace the execution of all of the Linq operators using described approach we would have to implement many extension methods, one for each Linq operator. How to avoid this ? LinqDebugger is the the answer ;) . If you are wondering what the lazy evaluation is and how to debug Linq to object queries this project can be very useful. Let’s see a very simple query :

var q =
    from i in Enumerable.Range(0, 12)
    where i > 5 && i % 2 == 0
    select i.ToString("C");

foreach (var s in q)
    Console.WriteLine(s);

Now let’s debug that query:

var q =
    from i in Enumerable.Range(0, 12).AsDebuggable()
    where i > 5 && i % 2 == 0
    select i.ToString("C");

foreach (var s in q)
    Console.WriteLine(s); 

After running this code you will find the following text on the console:

Select creation
Select begin
Where creation
Where begin
 predicate i => ((i > 5) && ((i % 2) = 0)) : (0) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (1) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (2) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (3) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (4) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (5) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (6) => True
Where end 6
 selector i => i.ToString("C") : (6) => 6,00 zł
Select end 6,00 zł
6,00 zł
Select begin
Where begin
 predicate i => ((i > 5) && ((i % 2) = 0)) : (7) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (8) => True
Where end 8
 selector i => i.ToString("C") : (8) => 8,00 zł
Select end 8,00 zł
8,00 zł
Select begin
Where begin
 predicate i => ((i > 5) && ((i % 2) = 0)) : (9) => False
 predicate i => ((i > 5) && ((i % 2) = 0)) : (10) => True
Where end 10
 selector i => i.ToString("C") : (10) => 10,00 zł
Select end 10,00 zł
10,00 zł
Select begin
Where begin
 predicate i => ((i > 5) && ((i % 2) = 0)) : (11) => False
Where end (no result)
Select end (no result)

This text shows how the query has been executed. There can find there information about enumerators object creation, about data passing from one enumerator to another and execution of all functions used inside the query. One thing worth mentioning is that everything is presented in the same order as it was executed. Having this information we can easily figure out for example in which iteration the exception has been thrown and what were the values processing by the query at that moment. If such text representation is hard to read for you I also provide the VS visualizer for ExecutionPlan type presenting the same information on the tree control (copy LinqDebugger.dll and LinqDebugger.Visualizer.dll files to C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers folder to make it available).

var executionPlan = new ExecutionPlan();

var q =
    from i in Enumerable.Range(0, 12).AsDebuggable(executionPlan)
    where i > 5 && i % 2 == 0
    select i.ToString("C");

foreach (var s in q)
    Console.WriteLine(s);

image

I am not going to describe here in details how LinqDebugger has been implemented, you can download the code and check this out yourself. As a hint I will just show you the signature of AsDebuggable method. Please notice what else you can pass to that method. We can choose which operators we want to trace using LinqOperators enum type or pass TextWriter object (Console.Out is set as a default TextWriter).

public static class LinqDebuggerExtensions
{
    public static IQueryable<T> AsDebuggable<T>(this IEnumerable<T> source, ExecutionPlan executionPlan,
        LinqOperators linqOperators, TextWriter textWriter)
    { ... }
}

[Flags]
public enum LinqOperators : long
{
    None = 0,
    Aggregate = 1,
    All = 2,
    Any = 4,
    AsQueryable = 8,
    Average = 16,
    Cast = 32,
    Concat = 64,
    Contains = 128,
    ...
}

[Serializable]
public sealed class ExecutionPlan
{
    public Expression Query { get; internal set; }
    public List<Record> Records { get; }
    public void Reset();
}
    
[Serializable]
public class Record
{
    public RecordType RecordType { get; internal set; }
    public MethodCallExpression OperatorCallExpression { get; internal set; }
    public object Result { get; internal set; }
    public LambdaExpression FuncCallExpression { get; internal set; }
    public string FuncCallName { get; internal set; }
    public object[] Arguments { get; internal set; }
}

Tracing similar information during Rx queries execution is even more useful because in most cases such queries are executed asynchronously so debugging them is really hard. Let’s debug Rx version of previous query using RxDebugger:

var q =
    from i in Enumerable.Range(0, 12).ToObservable().AsDebuggable(
        new DebugSettings {SourceName = "range", Logger = DebugSettings.ConsoleLogger})
    where i > 5 && i % 2 == 0
    select i.ToString("C");

q.Run(Console.WriteLine);


range.Where.Select.Subscribe()
range.Where.Subscribe()
range.Subscribe()
range.OnNext(0)
range.OnNext(1)
range.OnNext(2)
range.OnNext(3)
range.OnNext(4)
range.OnNext(5)
6,00 zł
range.OnNext(6)
range.Where.OnNext(6)
range.Where.Select.OnNext(6,00 zł)
range.OnNext(7)
8,00 zł
range.OnNext(8)
range.Where.OnNext(8)
range.Where.Select.OnNext(8,00 zł)
range.OnNext(9)
10,00 zł
range.OnNext(10)
range.Where.OnNext(10)
range.Where.Select.OnNext(10,00 zł)
range.OnNext(11)
range.OnCompleted()
range.Where.OnCompleted()
range.Where.Select.OnCompleted()
range.Where.Select.Dispose()
range.Where.Dispose()
range.Dispose()

As you can see this time a quite deferent information displayed on the screen and there is no VS visualizer available. It’s because the implementation of RxDebugger is totally different from LinqDebugger. But there are some additional features too. To understand how RxDebugger works I will show you the Debug method which gives us ability to trace single observable object instead of the whole Rx query.

var q =
    from i in Enumerable.Range(0, 12).ToObservable().Debug(
        new DebugSettings {SourceName = "range", Logger = DebugSettings.ConsoleLogger})
    where i > 5 && i % 2 == 0
    select i.ToString("C");

q.Run(Console.WriteLine);

range.Subscribe()
range.OnNext(0)
range.OnNext(1)
range.OnNext(2)
range.OnNext(3)
range.OnNext(4)
range.OnNext(5)
6,00 zł
range.OnNext(6)
range.OnNext(7)
8,00 zł
range.OnNext(8)
range.OnNext(9)
10,00 zł
range.OnNext(10)
range.OnNext(11)
range.OnCompleted()
range.Dispose()

 

public static IObservable<T> Debug<T>(this IObservable<T> source, DebugSettings settings, Func<T, object> valueSelector)
{
    Action<T> onNext = v => { };
    if ((settings.NotificationFilter & NotificationFilter.OnNext) == NotificationFilter.OnNext)
        onNext = v => 
        { 
            if (settings.Logger != null) 
                settings.LoggerScheduler.Schedule(() => settings.Logger(DebugEntry.Create(settings, NotificationFilter.OnNext, valueSelector(v)))); 
        };
        
    Action<Exception> onError = ... ;
    Action onCompleted = ... ;
    Action subscribe = ... ;
    Action dispose = ... ;
    
    return Observable.CreateWithDisposable<T>(o =>
    {
        var newObserver = Observer.Create<T>
        (
            v => { onNext(v); o.OnNext(v); },
            e => { onError(e); o.OnError(e); },
            () => { onCompleted(); o.OnCompleted(); }
        );

        subscribe();
        var disposable = source.Subscribe(newObserver);

        return Disposable.Create(() =>
        {
            dispose();
            disposable.Dispose();
        });
    });
}

public sealed class DebugSettings
{
    // defaults 
    public static Action<DebugEntry> DefaultLogger { get; set; }
    public static IScheduler DefaultLoggerSchduler { get; set; }       
    public static string DefaultMessageFormat { get; set; }

    //loggers
    public static Action<DebugEntry> ConsoleLogger { get; private set; }
    public static Action<DebugEntry> DebugLogger { get; private set; }
   
    public string MessageFormat { get; set; }
    public Action<DebugEntry> Logger { get; set; }
    public IScheduler LoggerScheduler { get; set; }
    public string SourceName { get; set; }
    public NotificationFilter NotificationFilter { get; set; }
    public OperatorFilter OperatorFilter { get; set; }

    static DebugSettings()
    {
        ConsoleLogger = n => Console.WriteLine(n.FormattedMessage);
        DebugLogger = n => Debug.WriteLine(n.FormattedMessage);

        DefaultLogger = DebugLogger;
        DefaultLoggerSchduler = Scheduler.CurrentThread;
        DefaultMessageFormat = "{0}.{1}({2})";
    }

    public DebugSettings()
    {
        SourceName = "";
        NotificationFilter = NotificationFilter.All;
        OperatorFilter = OperatorFilter.AllOperators;

        Logger = DefaultLogger;
        LoggerScheduler = DefaultLoggerSchduler;
        MessageFormat = DefaultMessageFormat;
    }
}

public class DebugEntry
{
    public string SourceName { get; set; }
    public string FormattedMessage { get; set; }
    public NotificationFilter Kind { get; set; }
    public Exception Exception { get; set; }
    public object Value { get; set; }
}

Debug method creates a new observable object on the top of given observable sources. Each observer passed to this observable source is wrapped into a new observer tracing information about calling Subscribe, Dispose methods at the IObservable level and OnNext, OnError, OnCompleted methods at the IObserver level. We can provide filter on Rx operators (OperatorFilter enum type) or logged information (NotificationFilter enum type). In LinqDebugger project TextWiter class has been used to log information. Here we have much more flexible solution because we can pass delegate type responsible for storing logged information. RxDebugger provides standard loggers such as DebugSettings.ConsoleLogger or DebugSettings.DebugLogger but we can also set our own delegate type or even merge many different logger delegates. Such a scenario will be presented in further part of the post. Once we know how Debug method works let’s reveal the secret behind the AsDebuggable method.

public interface IDebuggedObservable<T> : IObservable<T>
{
    DebugSettings Settings { get; }
}
    
public static partial class RxDebuggerExtensions
{    
    public static IDebuggedObservable<T> AsDebuggable<T>(this IObservable<T> source, DebugSettings settings)
    {
        return new DebuggedObservable<T>(source.Debug(settings), settings);
    }
        
    public static IDebuggedObservable<TSource> Where<TSource>(this IDebuggedObservable<TSource> source , Func<TSource,bool> predicate)
    {
        var settings = source.Settings.Copy();
        settings.SourceName = settings.SourceName +  ".Where";
        return new DebuggedObservable<TSource>((source as IObservable<TSource>).Where<TSource>(predicate).Debug(settings), settings);
    }
    public static IDebuggedObservable<TResult> Select<TSource,TResult>(this IDebuggedObservable<TSource> source , Func<TSource,TResult> selector)
    {
        var settings = source.Settings.Copy();
        settings.SourceName = settings.SourceName +  ".Select";
        return new DebuggedObservable<TResult>((source as IObservable<TSource>).Select<TSource,TResult>(selector).Debug(settings), settings);
    } 
    ... 
    
    private class DebuggedObservable<T> : IDebuggedObservable<T>
    {
        private readonly IObservable<T> _source;
        private readonly DebugSettings _settings;
        public DebugSettings Settings { get { return _settings; } }

        public DebuggedObservable(IObservable<T> source, DebugSettings settings)
        {
            _source = source;
            _settings = settings;
        }
        public IDisposable Subscribe(IObserver<T> observer)
        {
            return _source.Subscribe(observer);
        }            
    }
}

Of course I didn’t implement extension methods for all Rx operator manually, I wrote T4 template generating appropriate extension methods (currently 127 methods in .Net version and 125 methods in Silverlight version :) ). The best way to use RxDebugger in your projects is to add T4 template to the project you are working on and run template every time you change the version of Rx. It allows you to always be synchronized with Rx dlls. Finally let’s see how to use RxDebugger in Silverlight application.

<UserControl x:Class="Blog.SL.Post016.RxDebuggerTest"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <StackPanel>
        <TextBox x:Name="input"/>
        <TextBox x:Name="output"/>
        <ItemsControl x:Name="log"/>
    </StackPanel>
</UserControl>

 

public partial class RxDebuggerTest : UserControl
{
    public RxDebuggerTest()
    {
        InitializeComponent();

        var entries = new ObservableCollection<DebugEntry>();
        log.ItemsSource = entries;

        var q = input
            .GetObservableTextChanged()
            .Select(e => ((TextBox)e.Sender).Text)
            .AsDebuggable(new DebugSettings
                              {
                                  SourceName = "textChanged", 
                                  LoggerScheduler = Scheduler.Dispatcher, 
                                  Logger = DebugSettings.DebugLogger + entries.Add,                                      
                              })
            .Throttle(TimeSpan.FromSeconds(2))
            .Select(t => new string(t.Reverse().ToArray()));

        q.ObserveOnDispatcher().Subscribe(t => output.Text = t);
    }
}

image

And that’s it for the post. I encourage you to download and play with the two simple tools I provided here. They can be very helpful in debugging LINQ quires or learning about the internals of LINQ and Rx.
downlaod (Rx versions: .Net3.5 v1.0.2698.0 and SL3 v1.0.2698.0) Always check for newest version at the beginning of the post.

Thursday, November 12, 2009

Linq to ICollectionView

Currently I'm working on the project written in Silverlight and I have encountered an interface called ICollectionView and its standard implementation PagedCollectionView. In short, this components allow us to create the view of collection of items with filtering, grouping and sorting functionality. The idea behind this interface is very similar to DataView/DataTable mechanism. DataTable is responsible for storing data and DataView is just an appropriately configured proxy (only filtering and sorting in this case) which can be bound to UI controls. Let's look at a very simple example:

public class Number
{
    public int Value { get; set; }
    public int Random { get; set; }

    public static Number[] GetAll()
    {
        var random = new Random();
        return
            (from n in Enumerable.Range(1,5)
             from m in Enumerable.Repeat(n, n)
             select new Number {Value = n, Random = random.Next(10)}).ToArray();            
    }
}

// Silverlight
public class LinqToICollectionView : UserControl
{
    public LinqToICollectionView()
    {
        Number[] numbers = Number.GetAll();

        Content = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Children =
            {
                new DataGrid { ItemsSource = new PagedCollectionView(numbers).SetConfiguration()},
            }
        };
    }
}

public static class Configurator
{
    public static ICollectionView SetConfiguration(this ICollectionView view)
    {
        // filtering
        view.Filter = (object o) => ((Number)o).Value < 5;
        // grouping
        view.GroupDescriptions.Add(new PropertyGroupDescription("Value"));
        // sorting
        view.SortDescriptions.Add(new SortDescription("Value", ListSortDirection.Descending));
        view.SortDescriptions.Add(new SortDescription("Random", ListSortDirection.Ascending));
        return view;
    }     
}

image

But wait a minute, we said ... filtering, ordering, grouping ? Let's use LINQ query to configure ICollectionView:

public static class Configurator
{
    public static ICollectionView SetConfigurationWithLinq(this ICollectionView view)
    {
        var q =
            from n in new View<Number>()
            where n.Value < 5
            orderby n.Value descending, n.Random
            group n by n.Value;
        q.Apply(view);
        return view;
    }        
}

The whole implementation consists of 3 simple classes: View<T>, OrderedView<T> and GroupedView<T>.

public class View<T>
{
    public IEnumerable<GroupDescription> GroupDescriptions { get { ... } }
    public IEnumerable<SortDescription> SortDescriptions { get { ... } }
    public Func<T,bool> Filter { get { ... } }
    
    public View<T> Where(Func<T, bool> func) { ... }
    public SortedView<T> OrderBy<T2>(Expression<Func<T, T2>> func) { ... }
    public SortedView<T> OrderByDescending<T2>(Expression<Func<T, T2>> func) { ... }
    public GroupedView<T> GroupBy<T2>(Expression<Func<T, T2>> func) { ... }
    
    public void Apply(ICollectionView collectionView) { ... }
}
public sealed class SortedView<T> : View<T>
{    
    public SortedView<T> ThenBy<T2>(Expression<Func<T, T2>> func) { ... }
    public SortedView<T> ThenByDescending<T2>(Expression<Func<T, T2>> func)  { ... }
}
public sealed class GroupedView<T> : View<T>
{
    public GroupedView<T> ThenBy<T2>(Expression<Func<T, T2>> func) { ... }
}

Methods for sorting and grouping which take an expression tree as a parameter analyze the tree looking for indicated members (fields or properties) and collect appropriate SortDescription and GroupDescription objects. Where method takes a delegate type which is combined via logical and operator with existing filter delegate set previously (in case when Where method is called many times). Of course the same mechanism work also in WPF.

Number[] numbers = Number.GetAll();

// WPF
new Window
{
    Content = new StackPanel
    {
        Orientation = Orientation.Horizontal,
        Children =
        {
            CreateListView(new CollectionViewSource { Source = numbers }.View.SetConfiguration()),
            CreateListView(new CollectionViewSource { Source = numbers }.View.SetConfigurationWithLinq())
        }
    }
}
.ShowDialog();


private static ListView CreateListView(ICollectionView view)
{
    return new ListView
    {
        GroupStyle = { GroupStyle.Default },
        View = new GridView
        {
            Columns =
            {
                new GridViewColumn { Header = "Value", DisplayMemberBinding = new Binding("Value") },
                new GridViewColumn { Header = "Random", DisplayMemberBinding = new Binding("Random") },
            }
        },
        ItemsSource = view
    };
}

At the end I'd like to mention one interesting thing. We only support filtering, sorting and grouping and don't support for instance projection, joining and so on. That's way this code should compile:

var v1 = // only filtering specified
    from n in new View<Number>() 
    where n.Value < 5 
    select n;

var v2 = // grouping (last grouping definition overrides previous ones)
    from n in new View<Number>()
    group n by n.Random into s 
    group s by s.Value;

but this will not:

var v3 = // joining is not supported
    from p in new View<Number>()
    join pp in new[] { 1, 2, 3, 4 } on p.Random equals pp
    select p;

var v4 = // projection is not supported
    from p in new View<Number>()
    where p.Value > 5
    select p.Random;

var v5 = // at least one filtering, grouping or sorting definition must be specified
    from p in new View<Number>()
    select p;

var v6 = // Numer type is the only valid type of grouped element
    from p in new View<Number>()
    group p.Random by p.Value;

As a homework I leave you a question: why it works this way ? :)

Sources

Saturday, November 8, 2008

Use expression tree to avoid string literals in reflecting code part 2 (WorkflowArguments, WorkflowOutputParameters, Mapper)

Last time I was writing about a utility class called ReflectionHelper, this time I'll show you two real scenarios where this class or just expression tree have been used.

For last couple of months I've been working on a project built on the top of Workflow Foundation. Now we have C#3.0 many thinks can be done smarter, simpler, quicker, better or ... more cool ;) Let's look at a simple workflow class:

class MyWorkflow : SequentialWorkflowActivity
{
    public int MyInt { get; set; }
    public string MyString { get; set; }            

    public MyWorkflow()
    {
        CodeActivity codeActivity = new CodeActivity("codeActivity1");
        codeActivity.ExecuteCode += delegate
        {
            Console.WriteLine("MyInt : " + MyInt);                    
            Console.WriteLine("MyString : " + MyString);
            MyInt++;
            MyString = "yo";
        };
        Activities.Add(codeActivity);
    }
}

I know that not all of you had the opportunity to use WF so I'll try to give you some basics. The most elementary component in WF is an activity. We can say that activity is just a class with 'Excute' method responsible for doing some action. Workflow process is also an activity containg another activities which are executed one by one (that's why it derives from SequentialWorkflowActivity). Our workflow has only one activity CodeActivity which raises ExecuteCode event when it's executed. Additionally our process manipulates its state stored in properties MyInt and MyString. Let's see how to start this process and initialize its state:

using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{                
    var arguments = new Dictionary<string, object>()
        {
            {"MyString", "hello"},
            {"MyInt", Math.Max(5, 10)},
        };

    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyWorkflow), arguments);
    instance.Start();
}

The problem is that method CreateWorkflow takes a dictionary where the key is a property name and the value is a value of the property. But what if someone changes the name or the type of the property someday ? The code will compile fine but at runtime we will get an exception. Since we have C#3.0 we can very easily resolve these two problems.

var arguments = new WorkflowArguments<MyWorkflow>()
{
    { w => w.MyString, "hello" },
    { w => w.MyInt, Math.Max(5,10) }
};

WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyWorkflow), arguments);

public class WorkflowArguments<TWorkflow> : Dictionary<string,object>
{
    public WorkflowArguments<TWorkflow> Add<T>(Expression<Func<TWorkflow, T>> property,
        T propertyValue)
    {
        var propertyInfo = Blog.Post002.ReflectionHelper.GetProperty<TWorkflow,T>(property);
        Add(propertyInfo.Name, propertyValue);
        return this;
    }
}

The same technique we be used to process parameters after execution.

static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
    Console.WriteLine("workflowRuntime_WorkflowCompleted");
    var parameters = new WorkflowOutputParameters<MyWorkflow>(e.OutputParameters);

    Console.WriteLine(parameters.GetParameter( w => w.MyInt));
    Console.WriteLine(parameters.GetParameter( w => w.MyString));            
} 

public class WorkflowOutputParameters<TWorkflow> 
{           
    private Dictionary<string, object> Parameters { get; set; }
    
    public WorkflowOutputParameters(Dictionary<string, object> parameters)
    {           
        Parameters = parameters;
    }

    public T GetParameter<T>(Expression<Func<TWorkflow, T>> property)
    {
        var propertyInfo = Blog.Post002.ReflectionHelper.GetProperty<TWorkflow, T>(property);
        return (T)Parameters[propertyInfo.Name];
    }
}

The second example is a Mapper class. It's a quite common scenario when we map instance of class A into instance of class B. For example, we very often load some kind of DAL entity from database into memory then we map it to some kind of business entity. In many cases the shape of both types if very similar, they have the same properties/fields so the mapping code is very simple. It just transfers values of properties or fields from one object to another. Mapper class is a very simple class giving us the ability to record the mapping of two types to each other. Next we can execute mapping process specifying two instances of those classes and the direction of mapping. Lets assume that we have two types:

class CustomerDal
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Age { get; set; }            
    public char Gender { get; set; }
    public string City { get; set; }
    public string Street { get; set; }
}

class CustomerBO
{
    public int Id { get; private set;  }    // only getter
    public string Name { get; set; }        // exactly the same name
    public double Age;                      // field
    public char Sex { get; set; }           // another name
    public string Address { get; set; }     // more complicated mapping
}

Now we want to map an instance of CustomerDal type to instance of CustomerBo. Firstly we need to define how the properties of types should be transformed. Once we have it we can start mapping.

var m1 = new Mapper<CustomerDal, CustomerBO>    // A type, B type
  {
      {a => a.Id, b => b.Id, Direction.A2B},    // member of type A, member of type B, mapping direction
      {a => a.Name, b => b.Name},               // by default map in both directions
      {a => a.Age, b => b.Age},                  {a => a.Gender, b => b.Sex},
      { (a, b, d) => b.Address = a.City + " " + a.Street , Direction.A2B} 
        // code snippet executed during mapping
  };
      
var customerDal = new CustomerDal { Id = 1, Name = "Michael", 
    City = "Chicago", Street = "W Washington", Age = 25, Gender = 'M'};
    
var customerBO = new CustomerBO();
m1.Map(customerDal, customerBO);

customerBO.Name = customerBO.Name + "!";
customerBO.Sex = 'F';
customerBO.Age = customerBO.Age + 1;
         
m1.Map(customerBO, customerDal);

Again, instead of specifying mapped properties in code as string literals we use expression trees. Using expression trees is safer, cleaner and much more powerful. I showed you just two examples of real life application of ExpressionTrees that goes for beyond Linq. You saw the potential. Now imagine what you can do in your project with it.

The source code for both examples you can be found here.

Use expression tree to avoid string literals in "reflecting code" (ReflectionHelper)

Reflection is a very useful mechanism letting us build very smart and flexible solutions. It is used in many places in .Net framework, for instance in Windows Forms to identify bound members or in Workflow Foundation to pass some parameters to workflow instance and many others. Those two samples have one common thing, we have to use string literals in code to identify type members such as properties. And of course it's not a problem if the types we use are not changing, it means once specified, member won't be changed in the future. Like which shouldn't change like .net framework types (it shouldn't be change cause of backward compatibility).

Lets imagine that we bind one property of our business object to a TextBox's property Text and one day during refactoring someone else changes the name or the type of the property or even worse - deletes it. The code will compile correctly but we can't be sure how it will work at runtime because it depends on the sort of change. Maybe some exception will be thrown, maybe everything will look fine but the property won't be set after modifying text in the TextBox or maybe all will work just fine. Such bugs are very unpredictable and very hard to find. Wouldn't it be nice if we could know just after change about possible problems (compilation failed). Sometimes we know than the property is used in many places in the code, so we rename it via our IDE (for instance in Visual Studio we can choose option 'Refactor -> Rename...') and we want be sure that everything works fine. Is this possible ?

Today I'll show you a utility class called ReflectionHelper giving us the ability to realize mentioned scenario. Currently when we extract information about property via reflection we write something like this:

public class SomeClass
{
    public int InstanceProperty { get; set; }
    public static int StaticProperty { get; set; }
}

PropertyInfo property1 = typeof(SomeClass).GetProperty("InstanceProperty");
PropertyInfo property2 = typeof(SomeClass).GetProperty("StaticProperty");

With ReflectionHelper the same code can be written like this:

PropertyInfo property3 = ReflectionHelper.GetProperty((SomeClass o) => o.InstanceProperty );            
PropertyInfo property4 = ReflectionHelper.GetProperty(() => SomeClass.StaticProperty);

This is exactly what we wanted to achieve. We have created instance of PropertyInfo class without using any string literals. Now when we manually change the name of a property in one place, the code won't compile. If you rename it by 'Rename...' option in VS, code inside lambda expression will be changed too.

Now, lets see how ReflectionHelper works. ReflectionHelper is a static class with 2 methods extracting information about given property. One for static properties and one for instance. The implementation is quite short and looks like this:

public static PropertyInfo GetProperty<TObject,T>(Expression<Func<TObject,T>> p) 
{ 
    return GetPropertyImpl(p); 
}
public static PropertyInfo GetProperty<T>(Expression<Func<T>> p) 
{ 
    return GetPropertyImpl(p); 
}
private static PropertyInfo GetPropertyImpl(LambdaExpression p)
{
    return (PropertyInfo)((MemberExpression)(p.Body)).Member;
}

The key point to understand how the code works is a new feature of C#3.0 called expression trees. In new version of C# we can use lambda expression in code. There are two kinds of lambda expression where the body of the method is a single expression ( x => x.ToString() ) or one or many statements (x => {return x.ToString(); } ).

Func<int, int> expressionBody = (a) => a + 1;
Func<int, int> statementBody = (a) => { return a + 1; };

In many places we use lambda with single expression body just because it's shorter but there is a scenario when we have to use it. Generally when compiler sees lambda expression in code it's treated as an anonymous method, but lambda expression can be also used to build expression trees. Lets look at the example:

Expression<Func<int, int>> exp1 = (a) => a + 1;
Expression<Func<int, int>> exp2 = (a) => { return a + 1; }; 
// Error: A lambda expression with a statement body cannot be converted to an expression tree

Ok, but what is an expression tree actually? When compiler sees lambda with expression body not in the context of delegate type but in the context of special generic type 'System.Linq.Expressions.Expression<TDelegate>' a lot of code is generated behind the scenes.

ParameterExpression p;
Expression<Func<int, int>> exp1 = Expression.Lambda<Func<int, int>>
(
    Expression.Add // body
    (
        p = Expression.Parameter(typeof(int), "a"),
        Expression.Constant(1, typeof(int))
    ),
    new ParameterExpression[] { p } // parameters
);

The code of lambda expression is interpreted and translated into code that actually builds its structure. Use 'Expreesion Tree Visualizer' to better visualize the structure of expression tree.

When we look back to implementation of GetProperty method we can see that it takes an expression tree as a parameter. Inside the the method we make some assumptions about the structure of tree so we know exactly where information about property is stored. Of course if the structure of the tree would look differently, some exception could be thrown. The same technique can be used to extract information about fields, methods and constructors (ReflectionHelper has appropriate functionality). In case of getting information about the methods there are different ways of doing it.

public class SomeClass
{
    public void InstanceMethod(int i) { }
}

Instead of writing literal call

var method = typeof(SomeClass).GetMethod("InstanceMethod");

use ReflectionHelper like this:

var method = ReflectionHelper.GetMethod<SomeClass,int>(o => o.InstanceMethod);

or like this:

var method = ReflectionHelper.GetMethodByCall<SomeClass>(o => o.InstanceMethod(1));

The implementation looks like this:

public class ReflectionHelper
{    
    public static MethodInfo GetMethodByCall<TObject>(Expression<Action<TObject>> expression) 
    { 
        return GetMethodByCallImpl(expression); 
    }
    public static MethodInfo GetMethodByCall(Expression<Action> expression) // for static methods 
    { 
        return GetMethodByCallImpl(expression); 
    }
    private static MethodInfo GetMethodByCallImpl(LambdaExpression expression)
    {
        return ((MethodCallExpression)expression.Body).Method;
    }    
    
    public static MethodInfo GetMethod<TObject, T>(Expression<Func<TObject, Action<T>>> expression) 
    { 
        return GetMethodImpl(expression); 
    }
    public static MethodInfo GetMethod<T>(Expression<Func<Action<T>>> expression) // for static methods 
    { 
        return GetMethodImpl(expression); 
    }
    private static MethodInfo GetMethodImpl(LambdaExpression expression)
    {
        return (MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)expression.
            Body).Operand).Arguments.Last()).Value;
    }
}

When we use GetMethod method we don't need to write methods parameters inside brackets but we need to provide their types as generic method arguments (if parameters exist or method returns something). In the second approach we just write code executing method inside lambda expression. The code is never executed so we don't have to pass any correct arguments. These two approaches have one common disadvantage. When we change the signature of the method by changing parameters or return type, we need to change the code reflecting that method too. Maybe there is some solution but I couldn't find it :(

Full implementation of ReflectionHelper class with code presenting many different scenarios of using them can be found here. In the next post I'll show you how the ReflectionHelper is used in real life :) Stay tuned!