I am a firm believer in symmetry in frameworks and code. If there is a Do behavior then it seems intuitive to have an Undo behavior right alongside of it. Strangely enough there are sort behaviors all over .NET now, so you and I seldom have to write sorts algorithms like quick sort or radix sorts from scratch, but there is no unsort or randomize behavior in the framework. (DevExpress does include Unsorting in some of their controls like the ASPxTreeList, but I couldn’t find an unsort anywhere in the framework itself or help files.) and, occasionally one needs to randomize data.
Years ago I wrote a Blackjack game that shuffles cards much like—refer to Programming for Fun and Profit – Using the Card.dll at http://www.developer.com/net/net/article.php/3303671/Programming-for-Fun-and-Profit---Using-the-Carddll.htm. An employee, or so she said, from Harrah’s Casino in Biloxi called and asked if they could use the code to put on a CD and provide to gamers as sort of a pillow favor. I said sure. And, this week I was tinkering with some DLR (Dynamic Language Runtime) behaviors looking for cool things to do with Dynamic Objects when I came across Scott Hanselman’s blog post about dynamism—see http://www.hanselman.com/blog/CategoryView.aspx?category=DLR. In this post Scott demonstrated how to load an Iron Python script file and use the DLR to call a shuffle method in that file. Pretty cool.
Wondering as I often do I wondered what else could be shuffled using this approach. As a result I played with the concept of shuffle “Card” objects as well as arrays of data like the Employees table data in the Northwind database. Here is the sample and the steps to reproduce the results—the code is provided in Listing 1.
1. Download IronPython 2.6 for,NET 4.0. (You can find the installer at http://ironpython.codeplex.com/releases/view/36280)
2. After IronPython installs add references to a C# project (or a VB project) for the DLLs in the installation folder, including IronPython.dll, IronPythonModules.dll, Microsoft.Dynamic.dll, Microsoft.Scripting.Debugging.dll, and Microsoft.Scripting.dll
3. Add using statements for IronPython.hosting ad Microsoft.Scripting.Hosting; these namespaces will be used to load and call into the an IronPython script file
4. The code will set the current directory to the “IronPython 2.6 for .NET 4.0\Lib” folder and load random.py (an IronPython script) and supporting files.
5. Finally, the code will use ADO.NET to load data from the Employees table and a dynamic object to invoke random.py’s shuffle method, passing in some of the employee data
Listing 1: Using IronPython through a dynamic object to shuffle an array of employee names.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace DlrIronPyhonShuffleDemo
{
class Program
{
static void Main(string[] args)
{
Directory.SetCurrentDirectory(
"C:\\Program Files\\IronPython 2.6 for .NET 4.0\\Lib");
ScriptRuntime p = Python.CreateRuntime();
dynamic random = p.UseFile("random.py");
const string connectionString =
@"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True;" +
"MultipleActiveResultSets=True";
DataTable employees = new DataTable();
using(SqlConnection connection = new SqlConnection(connectionString))
{
const string sql = "SELECT * FROM Employees ORDER BY LastName";
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(employees);
}
var shortEmployees = from row in employees.AsEnumerable()
select new {First=row.Field<string>("FirstName"),
Last=row.Field<string>("LastName")};
var data = shortEmployees.ToArray();
random.shuffle(data);
Array.ForEach(data, (se)=>Console.WriteLine(se));
Console.ReadLine();
}
}
}
The ScriptRuntime object contains a script runtime for IronPython for .NET 4.0. The middle of the code is boilerplate ADO.NET code. The LINQ query creates a projection containing just employee first and last names. The IronPython file’s shuffle method threw an exception on the enumerable collection of employee data, but handled an array just fine. (It also handled an array of Card objects—a complex type—in another demo I tinkered with.) the code wraps up by shuffling the array of data and writing the contents to the Console.
I am not sure how performant such calls will be, but it may not always matter. It might be interesting to write a randomizer and compare shuffling results with managed .NET code versus a dynamic object call. (By the way dynamic random demonstrates how to use a dynamic object in C#; declare the type as Object in VB.) However, if performance isn’t an issue and you can find a solution in another dynamic language like IronPython calling an external method even in script may be useful. As I have stated in other posts, everything dynamic objects and the DLR might be used for probably haven’t been discovered yet, but the DLR is a clever and interesting addition to .NET programming.