jump to navigation

ApprovaFlow – A Proof of Concept March 25, 2011

Posted by ActiveEngine Sensei in .Net, .Net Development, ActiveEngine, Approvaflow, ASP.Net, C#, JSON.Net, LINQ, New Techniques, Open Source.
Tags: , ,
add a comment

Like Tolkien, Sensei wants to create the landscapes, cultures and languages before he writes his next epic. You can be the judge whether the work is a series of sketches and notes like the Silmarillion or cohesive, compelling story that you want read again and again. As a bonus Sensei will deliver working software that hopefully will be of use to you.  (Photo credit - utnapistim).

The epic will be called ApprovaFlow. ApprovaFlow is a framework / process / methodology that allows you to create workflow applications that are easy to deploy and are configurable. With ApprovaFlow Sensei hopes to demonstrate how to readily encorporate the inevitable changes that your users will ask of you. Deliver changes effortlessly and without groans. Cast off the chains inconvenient builds and focus on creating solutions that stay out of the users way.

Ok. Managent wants bullet points so here are our goals for ApprovaFlow:

• Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties.
•. Allow the state of a workflow to be peristed as an integer, string. Quicky fetch state of a workflow.
•. Create pre and post nprocessing methods that can enforce enforce rules or carry out actions when completing a workflow task.
•. Introduce new functionality while isolating the impact of the new changes. New components should not break old ones
•.Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user.
•. Use one. aspx page to processes user input for any type of workflow.
•. Provide ability to roll your own customizations to the front end or backend of your application.

There it is. These goals will probably take us a good amount of time to review and implement. Is it worth it? Hell yeah. We’ll end up with one simple project instead of a bloated framework where it takes forever to find anything. A nice by product will be that you can spend more time thinking about how to solve your users problems rather than trying to figure out a monsterous framework that requires a huge investment of energy and time learning how to get simple things done.

About these ads

Dynamically Create Test Data with NBuilder, JSON and .Net October 24, 2010

Posted by ActiveEngine Sensei in .Net, ActiveEngine, Ajax, ASP.Net, C#, Fluent, LINQ, Open Source, Problem Solving.
Tags: , , , , ,
5 comments

Part 1 of a 3 part series.  For the latest DataBuilder capabilities, read this post or download the new source code from here.

Building test data should be as easy:

var agentList = Builder<SalesAgent>.CreateListOfSize(5)
                           .WhereTheFirst(1)
                                  .Have(x => x.FirstName = "James")
                                  .And(x => x.LastName = "Kirk")
                            .AndTheNext(1)
                                  .Have(x => x.FirstName = "Bruce")
                                  .And(x => x.LastName = "Campbell")
                            .Build()
                            .ToList();

Wouldn’t be nice if all the properties of your objects were automatically populated:

Product:
       Id              : 1
       Title           : "Title1"
       Description     : "Description1"
       QuantityInStock : 1

NBuilder by provides you with a great fluent interface to accomplish this with ease.  You can even achieve scenarios where you can create hierarchies of data, set property values on a range objects in a list, and even create a specified range of values that you can use populate other objects.  Peruse through the samples and you will see, NBuilder quite capably maps values  the public properties of your objects.  A real time saver.

Sensei is going to kick it up a notch and provide you with a means to create test data with out having to recompile your projects.  This is ideal for when you want to create UI prototypes.  DataBulider uses CS-Script and NBuilder to create a web based data generation tool that can read assemblies and will allow you to script a process that will generate test data in the form of JSON.

This adventure is split into two parts.  First a quick demo, then instructions on how to configure DataBuilder for you environment.  A deeper discussion of CS-Script and embedded scripting in .Net will be part of the sequel to this action/adventure, as we all know the second movie in the series is always the best!.

Operating DataBuilder

In short you have three things to do:

  • Identify the assemblies that contains the objects you want to generate test data for.  The path to the files can be anywhere on your system.  For convenience there is an folder called Assembly that you can copy the files to.  Multiple assemblies from different locations can be imported.
  • Create the import statements.
  • Create the code snippet with the NBuilder statements that will generate your data.

Here’s a screen shot of DataBuilder with each section that corresponds with the three goals stated above.

And here is an example that we’ll be working with.

var agents = Builder<SalesAgent>.CreateListOfSize(5)
                    .WhereTheFirst(1)
                         .Have(x => x.FirstName = "James")
                         .And(x => x.LastName ="Kirk")
                    .AndTheNext(1)
                          .Have(x => x.FirstName = "Bruce")
                          .And(x => x.LastName = "Campbell"})
                    .Build()
                    .ToList();

parameters["JsonDataSet"] = JsonConvert.SerializeObject(agents);

Note that after the end of the code that creates the objects, you need to include a statement

parameters["JsonDataSet"] = JsonConvert.SerializeObject(List);

Without that statement you will not get your data serialized.  If you’ve entered the data as shown, hit the Build button and the resulting JSON is placed in the output box.  That’s it.  Looking through the output you’ll note that the first two sales dudes are James Kirk and Bruce Campbell, while the remaining records are completed by NBuilder.

[{"FirstName":"James","LastName":"Kirk","Salary":1.0,"RegionId":1,"RegionName":"RegionName1","StartDate":"\/Date(1287892800000-0400)\/"},{"FirstName":"Bruce","LastName":"Campbell","Salary":2.0,"RegionId":2,"RegionName":"RegionName2","StartDate":"\/Date(1287979200000-0400)\/"},{"FirstName":"FirstName3","LastName":"LastName3","Salary":3.0,"RegionId":3,"RegionName":"RegionName3","StartDate":"\/Date(1288065600000-0400)\/"},{"FirstName":"FirstName4","LastName":"LastName4","Salary":4.0,"RegionId":4,"RegionName":"RegionName4","StartDate":"\/Date(1288152000000-0400)\/"},{"FirstName":"FirstName5","LastName":"LastName5","Salary":5.0,"RegionId":5,"RegionName":"RegionName5","StartDate":"\/Date(1288238400000-0400)\/"}]

You also can load a script and execute it as well.  That’s done on the “Script Loader” tab.  The location of the scripts is set in the WebConfig and the key name is ScriptPath.  Here’s the screen shot:

Anatonomy of DataBuilder Script

Here’s the complete C# script file that builds your data.  It’s just a class:

//CSScript directives - DO NOT REMOVE THE css_ref SECTION!!!
//css_ref System.Core;
//css_ref System.Data.ComponentModel;
//css_ref System.Data.DataSetExtensions;
//css_ref System.Xml.Linq;

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using DataGenerator.Core;
using DataGenerator.ObjectTypes;
using DataGenerator.ScriptHost;
using System.Linq.Expressions;
using System.Linq;
using Newtonsoft.Json;
using FizzWare.NBuilder;
//  Add a reference to your assemblies as well!!
using UserDeploymentDomain;

public class CreateTestFile : IScriptRunner
{
    public void  RunScript(Dictionary parameters)
    {
        var agents = Builder.CreateListOfSize(5)
                    .WhereTheFirst(1)
                         .Have(x => x.FirstName = "James")
                         .And(x => x.LastName = "Kirk")
                    .AndTheNext(1)
                          .Have(x => x.FirstName = "Bruce")
                          .And(x => x.LastName = "Campbell")
                    .Build()
                    .ToList();

        parameters["JsonDataSet"] = JsonConvert.SerializeObject(agents);
    }

    public void  RunScript()
    {
 	    throw new NotImplementedException();
    }
}

The very top section “CSScript Directives” is required by CS-Script.  These are directives that instruct the CS-Script engine to include assemblies when it compiles the script.  The imports section is pretty straight forward.

You’ll note that the script inherits from an interface.  This is a convention used by CS-Script to allow the host and script to share their respective assemblies.  Sensei will discuss that in next post.  The RunScript method accepts a Dictionary that contains the parameters.  This will house the JsonDataSet that is expected for the screen to display the output of your data.

Advanced NBuilder Experiments
The beauty of NBuilder is that you can create test data that goes beyond “FirstName1″, and allows you to quickly create data that matches what the business users are used to seeing. If you think about it you should be able to generate test data that will exercise any rules that you have in the business domain, such as “Add 5% tax when shipping to New York”. With the scripting capability of DataBuilder you can create suites test data that can evolve as you test your system. You could also use the JsonDataSet to create mocks of your objects as well, maybe use them for prototyping your front end.

We’ll do a quick sample. Our scenario is to create assign real regions to sales agents. Furthermore, we want to only chose a range of regions and assign them at random.

First we build the Regions:

var regions= Builder<Region>.CreateListOfSize(4)
	.WhereTheFirst(1)
		.Have(x => x.State = "Texas")
	.AndTheNext(1)
		.Have(x => x.State = "California")
	.AndTheNext(1)
		.Have(x => x.State = "Ohio")
	.AndTheNext(1)
		.Have(x => x.State = "New York")
	.Build();

Now we’ll create a SalesAgents and using the Pick method from NBuilder we’ll randomly assign a region to the sales agents:

var agents = Builder<SalesAgent>.CreateListOfSize(5)
                    .WhereAll()
                           .HaveDoneToThem(x => x.RegionName = Pick.RandomItemFrom(regions).State)
                    .WhereTheFirst(1)
                         .Have(x => x.FirstName = "James")
                         .And(x => x.LastName = "Kirk")
                    .AndTheNext(1)
                          .Have(x => x.FirstName = "Bruce")
                          .And(x => x.LastName = "Campbell")
                    .Build()
                    .ToList();

The result set now has the range of states distributed to the Sales Agents. Looks like James Kirk needs to cover Texas. You may need to view the source to see the output.

[{"FirstName":"James","LastName":"Kirk","Salary":1.0,"RegionId":1,"RegionName":"Texas","StartDate":"\/Date(1287892800000-0400)\/"},{"FirstName":"Bruce","LastName":"Campbell","Salary":2.0,"RegionId":2,"RegionName":"Texas","StartDate":"\/Date(1287979200000-0400)\/"},{"FirstName":"FirstName3","LastName":"LastName3","Salary":3.0,"RegionId":3,"RegionName":"California","StartDate":"\/Date(1288065600000-0400)\/"},{"FirstName":"FirstName4","LastName":"LastName4","Salary":4.0,"RegionId":4,"RegionName":"California","StartDate":"\/Date(1288152000000-0400)\/"},{"FirstName":"FirstName5","LastName":"LastName5","Salary":5.0,"RegionId":5,"RegionName":"Ohio","StartDate":"\/Date(1288238400000-0400)\/"}]

Configure DataBuilder For Your Environment
Given that DataBuilder is loading assemblies you will want to run it on either your dev environment or on a test server where your co workers won’t mind if you need to take IIS up and down. Also, you’ll want to work with a copy of your assemblies in case you need to make a quick change. There are times when IIS will not release a file and if you need to make changes to the assemblies themselves it’s more convenient to copy them after you’ve re-compiled.

There are two settings you need to change in the WebConfig to match your environment.

ScriptPath - Point this to the share where you want to save any scripts. DataBuilder will scour the directory and list anything you place in there.

FizzWarePath - This needs to point to the location of the NBuilder dll. Most likely this will be the bin folder of the DataBuilder website. In the follow up post Sensei will explain what this does.

Wrapping Up For Now

We covered a lot on the whirlwind tour of DataBuilder.  There’s a lot more that is of interest, particularly with respects to the embedded scripting aspects provided by CS-Script.  For now, have fun playing building you data sets.  In the next installment we’ll cover the scripting aspect in more detail  For now, download and experiment.  Here’s the source for DataBuilder with unit tests.

Janga – A Validation Framework with a Fluent API September 26, 2010

Posted by ActiveEngine Sensei in .Net, ActiveEngine, Business Processes, C#, Design Patterns, Expression Trees, Fluent, LINQ, New Techniques, Problem Solving.
Tags: , , , , , ,
add a comment

Why can’t we  write code that read likes this:

bool passed = employee.Enforce()
                    .When("Age", Compares.IsGreaterThan, 45)
                    .When("Department", Compares.In, deptList)
                    .IsValid();
if(passed)
{
    SomeProcess();
}

One of the enduring challenges for software developers and business is to create abstractions that accurately represent concrete rules for business operations.  As opposed to operating like our tribal ancestors where you had to kill a goat, start a fire and listen to the blind boy tell the tale told for thousands of years, today we’d like to be able to read stories ourselves.  Hopefully the story that we read matches the reality of what we have implemented in our code.  Many nested if statements can quickly make verifying that the code matches the story very difficult.

A fluent validation API can assist with this.  Look at the code at the top of the post.  You can show that most people without having to get out the smelling salts.  For your fellow developers its creates a succinct way to express precisely what the logic is. They’ll love you for it.

Janga, a fluent validation framework for creating such an API.  There are three goals to be met here, and Janga fulfills these goals:

Goal 1 – Be able to chain “When” clauses together.  Each test – represented by the “When” clause – needs to chained together.

Goal 2 – Accept a test on any object property where the test criteria is defined in the form of x <= y at runtime.  The types of objects and their properties will not be known until runtime, so our framework must be able to analyze an object and construct a test against each property as it is presented.  This is NOT the specification pattern, where you define a delegates ahead of time.

Goal 3 –  Flexibly handle errors by either halting on the first error, or by proceeding with each test and logging each error as it is encountered.

The code Sensei will present here fulfills all of these goals and gives us the fluent magic we see in the sample at the top of this post.  Before we delve into the details, the sources for the ideas and explanations of Lambda Expressions, fluent apis, Expression trees,  should be acknowledged and applauded, because they got Sensei thinking along the right path:

Fluent Validation API

Roger Alsing – Fluent Argument Validation Specification

Raffaele Garofalo – How to write fluent interface with C# and Lambda.

Lambdas, Expression Trees, Delegates, Predicates

Expression Tree Basics – Charlie Calvert’s Community Blog

Marc Gravell – Code, code and more code.: Explaining Expression

Marc Gravell – Code, code and more code.: Express yourself

Implementing Dynamic Searching Using LINQ (check the section regarding dynamic expressions.)

Creating this api is a twisted cluster-wack of a zen puzzle.  The code for this solution consists of one class and three extension methods.  We’ll make use of generics, delegates and expression trees to evaluate our When clauses.  In the end we’ll see that with very little code we get a lot of mileage.  It took Sensei a long time to wrap his head around how to piece all of these things together, so hopefully the explanation will be clear.  Note that the solution has tests that demonstrate how to use the framework, so if you want to skip the madness and just try things out, go for it.

Goal 1:  Chaining When clauses together

To get the ball rolling, there is an extension method Ensure that will accept the object you wish to evaluate, encapsulate that object into a Validation class.

public static Validation<T> Enforce<T>(this T item, string argName,
    bool proceedOnFailure)
{
    return new Validation<T>(item, argName, proceedOnFailure);
}

Creating a chain of tests is accomplished with the Validation class and successive calls to the extension method When.  Validation encapsulates the object you wish to test.  In our examples that’s Employee.  Employee will be passed on to When, When executes a test and stores the results in Validation.  After the test, When returns Validation, and this creates the opportunity to execute another extension method.

public class Validation<T>
{

    public T Value { get; set; }
    public string ArgName { get; set; }
    public bool ProceedOnFailure { get; set; }
    public bool IsValid { get; set; }
    public IList<string> ErrorMessages { get; set; }

    public Validation(T value, string argName)

    {

        this.ArgName = argName;
        this.Value = value;
        this.ProceedOnFailure = false;

        //  Set to valid in order to allow for different chaining of validations.
        //  Each validator will set value relative to failure or success.
        this.IsValid = true;
        this.ErrorMessages = new List<string>();

}

     public Validation(T value, string argName, bool proceedOnFailure)
    {
        this.ArgName = argName;
        this.Value = value;
        this.ProceedOnFailure = proceedOnFailure;

        //  Set to valid in order to allow for different chaining of validations.
        //  Each validator will set value relative to failure or success.

        this.IsValid = true;
        this.ErrorMessages = new List<string>();
    }
}

Signature of When (note that we return Validation):

public static Validation<T> When<T>(this Validation<T> item, string propertyName, Compare compareTo, object propertyValue)

Before we continue on with reviewing dynamic evaluation by the When clause, you could stop here and still have a useful mechanism for creating validation routines.  That is, you could create a extension method for each validation you want to perform.  One example could be:

public static Validation<Employee> LastNameContains(

        this Validation<Employee> employee, string compareValue)

{

    var result = employee.Value.LastName.Enforce("LastName",

                  employee.ProceedOnFailure).Contains(compareValue);

    employee.IsValid = result.IsValid;

    result.ErrorMessages

            .ToList()

            .ForEach(x => employee.ErrorMessages.Add("LastName => " + x));

    return employee;

}

So instead of Ensure.When you will use Ensure.LastNameContains(“Smi”).  You will also have to create a new method for each condition.  This is still quite expressive and would go a long way to keeping things organized.  This would be more in the spirit of the specification pattern.

Goal 2:  Dynamically Evaluating Tests at Runtime

As stated, the “tests” are performed with extension method When.  When accepts the Validation object, along with propertyName and the propertyValue that you are testing.  The enum Compare determines the type of test to perform.  The comparisons are:

public enum Compare
{
    Equal = ExpressionType.Equal,
    NotEqual = ExpressionType.NotEqual,
    LessThan = ExpressionType.LessThan,
    GreaterThan = ExpressionType.GreaterThan,
    LessThanOrEqual = ExpressionType.LessThanOrEqual,
    GreaterThanOrEqual = ExpressionType.GreaterThanOrEqual,
    Contains = ExpressionType.TypeIs + 1,
    In = ExpressionType.TypeIs + 2
}

The magic of When stems from the use of Expression trees as delegates.  As defined on MSDN, an expression tree is:

Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.

You can compile and run code represented by expression trees. This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries.

This gives you the ability, at runtime, to dynamically evaluate an expression in the form of x = y, also referred to as a binary expression.  And in our case, we wish to evaluate:  Employee.Age = = 45.  The delegate takes care of presenting the type of the Expression and it’s components to the runtime engine.

Marc Gravell explains the difference between a delegate and an Expression as:

  • The delegate version (Func<int,int,bool>) is the belligerent manager; “I need you to give me a way to get from 2 integers to a bool; I don’t care how – when I’m ready, I’ll ask you – and you can tell me the answer”.
  • The expression version (Expr<Func<int,int,bool>>) is the dutiful analyst; “I need you to explain to me - if I gave you 2 integers, how would you go about giving me a bool?”
  • In standard programming, the managerial approach is optimal; the caller already knows how to do the job (i.e. has IL for the purpose). But the analytic approach is more flexible; the analyst reserves the right to simply follow the instructions “as is” (i.e. call Compile().Invoke(…)) – but with understanding comes power. Power to inspect the method followed; report on it; substitute portions; replace it completely with something demonstrably equivalent, etc…

.NET 3.5 allows us to create “evaluators” with Lambda Expressions compiled as delegates that will analyze an object type, the comparisons we can make, and the values we want to compare dynamically. It will then execute that tiny block of code. This is treating our code as a set of objects.  A graph representing this tree looks like so:

Each node on the tree is an Expression. Think of this as a “bucket” to hold a value, a property or an operation.  For the runtime engine to know what the type and parameters of the Expressions are, we create a delegate from the Lambda expression of that node.  In other words, we let the compiler know that we have an expression of type Employee and will evaluate whether Employee.Age is equal to 45.

To accomplish the magic at runtime, you need to set up “buckets” to hold Employee.Age or Employee.FirstName and their values with their respective type for evaluation.  Furthermore we want to be able to evaluate any type of binary expression, so our Expression will make use of generics and a tiny bit of reflection so that we will have code that “parses” the object and it’s properties dynamically.

The Extension Method When:

public static Validation<T> When<T>(this Validation<T>; item, string propertyName, Compare compareTo, object propertyValue)

Creating the delegate of the Lambda expression:

//  Determine type of parameter.  i.e. Employee
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");

//  Property on the object  to compare to.  i.e. Employee.Age
Expression property = Expression.Property(parameter, propertyName);

//  The propertyValue to match.  i.e 45
Expression constant = Expression.Constant(propertyValue, propertyValue.GetType());

This takes care of the X and Y of the binary expression, but the next task is to create the comparison as an Expression as well:

Expression equality = CreateComparisonExpression<T>(property, compareTo, constant);

The type of comparison is determined by the enum Compare.  Once these steps are completed we convert the expression into a delegate with the statement:


var executeDelegate = predicate.Compile();

If you are worried about performance and the use of reflection, note that the use of static will greatly minimize this impact.  Basically you’ll take the performance hit on the first run but not on the subsequent runs.

Goal 3:  Error Reporting

For error reporting, Validation requires the name of the object with the property ArgName, and asks that you specify whether you wish to halt when there is an error.  This is accomplished with ProceedOnFailure.  An error log is created when you wish all tests to complete despite their respective results.  When you want to halt on the first error and throw an exception set the ProceedOnFailure to false.

Reporting the errors themselves takes place in each When clause, and this is implemented at the end of the When extension method.

//  Report Error handling
if(item.IsValid == false)
{
    if(item.ProceedOnFailure)
    {
        item.ErrorMessages.Add("When " + item.ArgName + "."
            + propertyName + " " + compareTo.ToString()
            + " " + propertyValue + " failed.");
    }
    else
    {
        throw new ArgumentException("When " + item.ArgName + "."
            + propertyName + " " + compareTo.ToString()
            + " " + propertyValue + " failed.");
    }
}

Finally we need to return the Validation object so that we can chain another When operation

To recap, When is a dynamic filter where at runtime, code is evaluated and created on the fly to analyze and execute a tree representing code as an object.  The expression trees can be applied to any object and evaluate the object’s properties.  Holy snikes!!!  If that doesn’t scare you how ‘bout chaining When’s together by always returning a Validation object so that you continue to apply another extension method to it.  Twisted Zen mind torture indeed, since we have complicated looking code so that we can less complicated “business code”.

Here is the source code with unit tests.

Persistent AnonymousTypes and Querying with Linq September 19, 2010

Posted by ActiveEngine Sensei in .Net, ActiveEngine, C#, Expression Trees, LINQ.
Tags: , , ,
1 comment so far

For those of us who are C# developers we are familiar with an anonymous type, defined as:

Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type. The type name is generated by the compiler and is not available at the source code level. The type of the properties is inferred by the compiler.

A neat feature, but once the anonymous object falls out of scope you no longer can use it.  Hugo Bonacci, creator of CSMongo and jLinq has created a class called AnonymousType that will allow you to persist an anonymous type beyond the scope of the method that creates that object.  In other words he has process that will allow to define an anonymous object on the fly such as:


AnonymousType.Create(new
 {
 Name = name,
 Department = dept
 });

This a bit of a paradigm shift, since you now can not access the object’s properties with a Getter: instead, you use a statement like:

string name = anonymousType.Get<int>("Name");

This is great but how would you query a List?  Certainly with AnonymousType as an object you may have a collection of these objects especially since this construct lends itself to being an all purpose DTO, or even function like a SharePoint list.

Querying a collection of AnonymousTypes is possible through the use of Expression Trees.  Using this technique you can query a list of AnonymousTypes with the following syntax:

var dept13 = agentList.AsQueryable()
                .Where(x => x.Has<int>("Department", Compare.Equal, 13);

Sensei’s solution is comprised of a Has() method on the AnonymousType class, and a static class AnonPredicates with Evaluate and CreateComparisonExpression methods.  Here’s the source project with unit tests.

AnonymousType.Has

public bool Has<T>(string propertyName, Compare comparesTo, object objectValue)
{
var value = this.Ge<T>(propertyName);

return AnonPredicate.Evaluate<T>(value, comparesTo, objectValue);
}

Has() is the starting point.  The first step is to get the current value of the property you wish to compare with the test value.  Since the properties of the AnonymousType are stored in a Dictionary you have to fetch that first.  The “T” of generic type will allow you to use the Has method for all types.  “T” will also tell the AnonymousType class the type that the property should be cast to.  This allows the class to determine what to do at runtime, and eliminates the need for you write methods per type, such as HasInt(), HasDouble(), HasString(), etc.

Has<T>() then passes the value, the type of comparison and the expected object to an evaluation method.

AnonPredicate.Evaluate


public static bool Evaluate<T>(T propertyValue, Compare comparesTo, object objectValue)
 {
 ParameterExpression parameter = Expression.Parameter(typeof(T), "x");

 Expression leftConstant = Expression.Constant(propertyValue, typeof(T));
 Expression rightConstant = Expression.Constant(objectValue, objectValue.GetType());

 var comparison = CreateComparisonExpression<T>(leftConstant, comparesTo, rightConstant);
 Expression<Func<T, bool>> predicate =
 Expression.Lambda<Func<T, bool>>(comparison, parameter);

 var execDelegate = predicate.Compile();
 return execDelegate(propertyValue);
 }

Evaluate will build an expression tree of the form “x == y”, where x is the value of the AnonymousType property as Constant, == is the comparison operation, and y is the compared value as Constant.  There is no dynamic look up of the AnonymousType property as we did that previously in the calling method Has().  Here we are just building a simple expression, and will determine if invoking that expression will yield a true or a false.

The parameter comparesTo is an Enumeration representing the equality expression to use:

public enum Compare
 {
 Equal = ExpressionType.Equal,
 NotEqual = ExpressionType.NotEqual,
 LessThan = ExpressionType.LessThan,
 GreaterThan = ExpressionType.GreaterThan,
 LessThanOrEqual = ExpressionType.LessThanOrEqual,
 GreaterThanOrEqual = ExpressionType.GreaterThanOrEqual,
 Contains = ExpressionType.TypeIs + 1,
 In = ExpressionType.TypeIs + 2
 }

Evaluate calls CreateComparisonExpression to build an equality expression.

CreateComparisonExpression

public static Expression CreateComparisonExpression<T>(Expression left, Compare comparesTo, Expression right)
 {
 switch (comparesTo)
 {
 case Compare.Equal:
 return Expression.Equal(left, right);

 case Compare.GreaterThan:
 return Expression.GreaterThan(left, right);

 case Compare.GreaterThanOrEqual:
 return Expression.GreaterThanOrEqual(left, right);

 case Compare.LessThan:
 return Expression.LessThan(left, right);

 case Compare.LessThanOrEqual:
 return Expression.LessThanOrEqual(left, right);

 case Compare.NotEqual:
 return Expression.NotEqual(left, right);

 case Compare.Contains:
 MethodInfo contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
 return Expression.Call(left, contains, right);

 case Compare.In:
 //  You are accepting a List&lt;T&gt;, where T corresponds to the property on your class
 //  I.E.  List&lt;int&gt; =&gt; Employee.Age as Integer.
 //  Comparison is Left Compares Right, hence you need the type of Left
 return Expression.Call(typeof(Enumerable), "Contains", new Type[] { left.Type }, right, left);

 default:
 throw new ArgumentException("Query.CreateComparisonExpression - comparison not supported");

 }

Here a simple switch is used to build and return our equality expression.  This is really a binary expression with a left and right constant coupled with the type of equality.

Take note of Contains and In at lines 23 and 27.  These use a bit reflection to call .Net methods to perform the comparison.  Contains will work for strings, while In works like the SQl In-clause and accepts an array of objects to test.  This eliminates the need for you to write multiple Or clauses and keeps your code more readable.

Back To Evaluate()

So far, we’ve accepted an enum that tells what operation to perform and have built and expression tree that will tell us is “x >= y” is true.  We build the Lambda expression with the line:

Expression<Func> predicate =
Expression.Lambda<Func>(comparison, parameter);

The last two line of Evaluate()  will execute the expression tree for us.  Before we execute we must compile the tree:

var execDelegate = predicate.Compile();

This makes the code executable. Next we run the code:

return execDelegate(propertyValue);

The code will yield a true or false, and we return this result.

Well, so what?

Remember our goal? We wanted to create a process that would examine the innards of an AnonymousType, return true when that property met a condition. This would let us do the following:

//  Find all agents in Department 13 or 21
int[] inList = new int[2]{13, 21};
var dept13_21 = agentList.AsQueryable()
                 .Where(x=> x.Has<int>("Department", Compare.In, inList));

Enough Wax-on / Wax-off.  Show me Crane Style!

You’ve done well Daniel-san.  Now apply your knowledge.  Even with all the syntax-sugar, what if you need to find all AnonymousTypes that have an Age property whose value is between 40 and 60?  Yes you could write this way:


var agentsAgeBetween40_60 = anonAgents.AsEnumerable()
 .Where(x => ( x.Has<int>("Age", Compare.GreaterThanOrEqual, 40) & (x.Has<int>("Age", Compare.LessThanEqual, 60)))
 .ToList();

But look at that mess!  If you don’t know karate you’ll have to learn it quick because your co-workers are going to hunt you down when they have to support this code.

Sensei’s shumatsu dosa ichi (“after class exercise number one”) is the Between method:


public bool Between<T>(string propertyName, T bottomRange, T topRange)
 {
 var value = this.Get<T>(propertyName);

 return ((AnonPredicate.Evaluate<T>(value, Compare.GreaterThanOrEqual, bottomRange))
 &amp; (AnonPredicate.Evaluate<T>(value, Compare.LessThanOrEqual, topRange)));
 }

Now we write our query as:

var salesAgesBetwee40_60 = agentList.AsQueryable()
.Where(x => x.Between("Age", 40, 60));

The Fung-Shui Kid Part 11

“Oh yeah, old man,” you say.  “How about karating this compound statement:  Show me all sales agents in between the ages of 30 and 40 whose first names begin with ‘St’!”

Before Sensei left the temple he gobbled down a dose of PredicateBuilder by Joe and Ben Albahari that allows him to create dynamic compound lambda expressions!  Shumatsu dosa ni (“after class exercise number two”) proceeds thusly:

public static Expression<Func<T, bool>> True<T>() { return f => true; }
    public static Expression<Func<T, bool>> False<T>() { return f => false; }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                        Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
              (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                         Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;
              (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
    }

So like Neo, now we don’t even have to dodge the bullets, as we’re writing this:


var predicate = PredicateBuilder.False<AnonymousType>();
 predicate = predicate.Or(x => x.Between<int>("Age", 40, 60));
 predicate = predicate.Or(x => x.Has<string>("Name", Compare.Contains, "St"));

 var salesAgentsBetwee40_60_STInName = agentList.AsQueryable()
 .Where(predicate);

The Return of the Sensei

Recapping all the action, we can create AnonymousTypes and access its properties in other calling methods.  In the middle of the fracas – or on the fly for you .Net types – when can create a class that serves as an anonymous type this can be passed to other methods.  As this lives as a regular object, we can create collections or lists of these objects and filter them using LINQ, Expression Trees, and the awesome PredicateBuilder.  Here are the source files.

Stay tuned – next time we leave the temple and hunt for beer!!  If you want to read more, gaze through these ancient scrolls from the masters:

Expression Tree Basics – Charlie Calvert’s Community Blog

Marc Gravell – Code, code and more code.: Explaining Expression

Marc Gravell – Code, code and more code.: Express yourself

Implementing Dynamic Searching Using LINQ (check the section regarding dynamic expressions.)

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: