The official Fatica Labs Blog! RSS 2.0
# Monday, 23 January 2012

… without writing a LinqToSomething provider, of course. The Expression.<Func<T>> construction is sometimes a little frightening since we suppose to have to write some complex tree navigation in order to achieve the expression behavior, but this is not always true, there is scenarios in which we can use it without any complex tree visit. In this post we will see some real world examples using this strategy.

1) INotifyPropertyChanged without “magic strings”

This interface is implemented in its simplest form:

public string CustomerName
{
   get
   {
	   return this.customerNameValue;
   }
   set
   {
	   if (value != this.customerNameValue)
	   {
		   this.customerNameValue = value;
		   NotifyPropertyChanged("CustomerName");
	   }
   }
}

We can leverage Linq.Expression here by this simple base class:

class PropertyChangeBase: INotifyPropertyChanged
{
	protected void SignalChanged<T>(Expression<Func<T>> exp)
	{
		if (exp.Body.NodeType == ExpressionType.MemberAccess)
		{
			var name = (exp.Body as MemberExpression).Member.Name;
			PropertyChanged(this, new PropertyChangedEventArgs(name));
		}
	   else
		   throw new Exception("Unexpected expression");
   }
   #region INotifyPropertyChanged Members
   public event PropertyChangedEventHandler PropertyChanged = delegate { };
   #endregion
}

By deriving our class from this one, we can easily notify a property change by writing:

SignalChanged(()=>CustomerName);


This allow us to leverage intellisense, and it is refactoring friendly, so we can change the name of our property without pain. The first project I seen using this technique was Caliburn Micro, but I’m not sure is the only one and the first. Same technique is used here to test the INotifyPropertyChange behavior.

2) Argument Verification

Really similar to the problem above, we want to avoid:

static int DivideByTwo(int num) 
{
   // If num is an odd number, throw an ArgumentException.
   if ((num & 1) == 1)
	   throw new ArgumentException("Number must be even", "num");

   // num is even, return half of its value.
   return num / 2;
}


In this case we are typing NUM, that is the name of the argument, as a literal string which is bad. We would preferably write something like this:

public void DoSomething(int arg1)
{
	Contract.Expect(() => arg1)
       .IsGreatherThan(0)
       .IsLessThan(100);
;
}

That again give us intellisense and refactoring awareness. You can find he code for this helper class here, and a brief description in this post.

3) The MoQ mocking library

The MoQ library is a .NET library for creating mock objects easy to use that internally leverage Linq.Expression to achieve such a readable syntax:

   mock.Setup(framework => framework.DownloadExists("2.0.0.0"))
       .Returns(true)
       .AtMostOnce();

4) A generic Swap function:

The simplest way in creating a generic Swap function in c# is:

void Swap<T>(ref T a, ref T b)
{
   T temp = a;
   a = b;
   b = temp;
}

Unfortunately, this won’t work if we want swap two property of an object, or two elements of an array. We would like to write something like this:

   var t = new Test_() { X = 0, Y = 1 };
   Swapper.Swap(() => t.X, () => t.Y);
   Assert.AreEqual(0, t.Y);
   Assert.AreEqual(1, t.X);

or with arrays:

    int[] array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Swapper.Swap(() => array[0], () => array[1]);
    Assert.AreEqual(2, array[0]);
    Assert.AreEqual(1, array[1]);

We can achieve this by a simple helper class using Linq.Expression:

public class Swapper
{
        public static void Swap(Expression<Func<T>> left, Expression<Func>T>> right)
        {
            var lvalue = left.Compile()();
            var rvalue = right.Compile()();
            switch (left.Body.NodeType)
            {
              case ExpressionType.ArrayIndex:
                  var binaryExp = left.Body as BinaryExpression;
                  AssignTo(rvalue, binaryExp);
                  break;

              case ExpressionType.Call:
                  var methodCall = left.Body as MethodCallExpression;
                  AssignTo(rvalue, methodCall);
                  break;
				  
              default:
                  AssignTo(left, rvalue);
                  break;
          }

          switch (right.Body.NodeType)
          {
              case ExpressionType.ArrayIndex:
                  var binaryExp = right.Body as BinaryExpression;
                  AssignTo(lvalue, binaryExp);
                  break;

              case ExpressionType.Call:
                  var methodCall = right.Body as MethodCallExpression;
                  AssignTo(lvalue, methodCall);
                  break;

              default:
                  AssignTo(right, lvalue);
                  break;
          }
      }

      private static void AssignTo<T>(T value, MethodCallExpression methodCall)
      {
          var setter = GetSetMethodInfo(methodCall.Method.DeclaringType,methodCall.Method.Name);
          Expression.Lambda<action>(
              Expression.Call(methodCall.Object, setter, Join(methodCall.Arguments, Expression.Constant(value)))
          ).Compile()();
      }

      private static Expression[] Join(ReadOnlyCollection<expression> args,Expression exp)
      {
          List<expression> exps = new List<expression>();
          exps.AddRange(args);
          exps.Add(exp);
          return exps.ToArray();
      }

      private static MethodInfo GetSetMethodInfo(Type target, string name)
      {
          var setName = Regex.Replace(name, "get", new MatchEvaluator((m) =>
          {
              return m.Value.StartsWith("g")?"set":"Set";
          })
          ,RegexOptions.IgnoreCase);
          var setter = target.GetMethod(setName);
          if (null == setter)
          {
              throw new Exception("can't find an expected method named:" + setName);
          }
          return setter;
      }

      private static void AssignTo<T>(Expression<Func<T>> left, T value)
      {
          Expression.Lambda<Func<T>>(Expression.Assign(left.Body, Expression.Constant(value))).Compile()();
      }

      private static void AssignTo<T>(T value, BinaryExpression binaryExp)
      {
          Expression.Lambda<Func<T>>(Expression.Assign(Expression.ArrayAccess(binaryExp.Left, binaryExp.Right), Expression.Constant(value))).Compile()();
      }
  }

This code leverages a samples by Takeshi Kiriya, I just added the ability in handling array to his own the original code.

5) Unit testing the presence of an attribute

Thomas Ardal talks in this post about how to easily unit test the presence of an attribute on a method of a class,  useful for example in MVC scenarios, or in others AOP circumstances.

A test leveraging his strategy is written as below:

    var controller = new HomeController();
    controller.ShouldHave(x => x.Index(), typeof(AuthorizeAttribute));

So we show five different simple application, I hope you find here some inspiration for your works, and feel free to write about your own ideas and enrich the list.

Monday, 23 January 2012 16:05:16 (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
C# | CodeProject | Linq

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

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

© Copyright 2017
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 124
This blog visits
All Content © 2017, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano