Apr 14, 2011

C# gotcha

Consider you have the following code:

SomeClass reference = null;
Console.WriteLine(reference.Echo("echo"));

Your first thought might be “NullReferenceException”. Ha, think again! What if you have an class defining an extension method like this:



public static class SomeClassExt
{
public static string Echo(this SomeClass x, string str)
{
return str;
}
}

You have been warned :)

Mar 9, 2011

Async Producer-Consumer with Linq, IEnumerable<T> and Threading.Tasks

Lately I’ve been dealing a lot with IEnumerable<T> classes and the yield return keyword. I found it really useful for stream like processing of otherwise really memory consuming operations. The workflow looks like this:
- Retrieve Item 1 (yield return)
- Process Item 1 (GetNext())
- ….
- Retrieve Item N
- Process Item N
The total time it takes to process the whole operation is:

N x AvgTime(Retrieve) + N x AvgTime(Process)

So I was thinking how to parallelize the whole operation, preferably in a Linq fashion, so it could fit into my existing code. Here is the result, using the (relatively) new System.Collections.Concurrent namespace and the Task Parallel Library:


using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

static class Extension
{
public static IEnumerable<TResult> SelectAsync<TProduct, TResult>(
this IEnumerable<TProduct> producer,
Func<TProduct, TResult> consumer,
int? productsBoundedCapacity = null,
int? resultsBoundedCapacity = null)
{
var productsQueue = productsBoundedCapacity.HasValue
? new BlockingCollection<TProduct>(productsBoundedCapacity.Value)
: new BlockingCollection<TProduct>();
var resultsQueue = resultsBoundedCapacity.HasValue
? new BlockingCollection<Tuple<int, TResult>>(resultsBoundedCapacity.Value)
: new BlockingCollection<Tuple<int, TResult>>();
Task.Factory.StartNew(() =>
{
foreach (var product in producer)
{
productsQueue.Add(product);
}
productsQueue.CompleteAdding();
});
Task.Factory.StartNew(() =>
{
var tasks = productsQueue
.GetConsumingEnumerable()
.Select((product, ind) => Task.Factory.StartNew(() =>
resultsQueue.Add(new Tuple<int, TResult>(ind, consumer(product)))))
.ToArray();
Task.WaitAll(tasks);
resultsQueue.CompleteAdding();
});
return resultsQueue
.GetConsumingEnumerable()
.OrderBy(x => x.Item1)
.Select(x => x.Item2);
}
}

Note however, that the producer part parallelizes correctly only with the usage of true enumerables that yield return the long running operation result (Arrays, List etc. already contain all the data). Here is a small proof of concept app:



class Program
{
private static IEnumerable<int> Producer()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(50); // long running operation
yield return i;
}
}

private static int Consumer(int item)
{
Thread.Sleep(100); // long running operation
return item * item;
}

static void Main()
{
var sw = new Stopwatch();
sw.Start();
var resultSync = Producer().Select(Consumer).Sum();
sw.Stop();
Console.WriteLine("Result: {0}, {1}ms", resultSync, sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
var resultAsync = Producer().SelectAsync(Consumer).Sum();
sw.Stop();
Console.WriteLine("Result: {0}, {1}ms", resultAsync, sw.ElapsedMilliseconds);
Console.ReadLine();
}
}

See ya!

Feb 10, 2011

MVC – Unit Testing JsonResult Actions

Today I had to write a unit test for a Asp.net MVC controller that returned a JsonResult. The Controller’s code looked somewhat like this:


[HttpPost]
public JsonResult JsonData(Query query)
{
// ... process query, get total_row_cnt and rows
return Json(new { total_row_cnt = rowCount, rows });
}

I often return anonymous types as JsonResult, just because I don’t want to have additional return model classes for JavaScript that are used only by one controller action and nowhere else.


And what about unit testing such actions? Sure JsonResult exposes a property called Data (of type object), that contains the argument passed to the Controller’s Json() call. If the type of the Data is known you can easily cast it to the known type and do further processing. But what if you pass an anonymous type as data to the JsonResult? How can you verify the results then?


Well you have the following options:


  • convert the anonymous type to a class,

  • directly use reflection on the returned object (magic strings!),

  • or make use of C# 4 dynamics!


The first two options are trivial, and I’m going to discuss only the last option. Simply casting the JsonResult.Data won’t do, since the type object does not implement the necessary infrastructure. I decided to implement a wrapper class that implements DynamicObject. Since anonymous types can offer only readonly properties all I had to do was to override the TryGetMember method. So here is the implementation:



using System;
using System.Dynamic;
using System.Reflection;

public sealed class AnonymusDynamicGetWrapper : DynamicObject
{
private readonly Type _subjectType;
private readonly object _subject;
public static dynamic Create(object subject)
{
return new AnonymusDynamicGetWrapper(subject);
}
private AnonymusDynamicGetWrapper(object subject)
{
_subject = subject;
_subjectType = subject.GetType();
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
var propertyInfo = _subjectType.GetProperty(binder.Name);
if (propertyInfo == null) return false;
var getter = propertyInfo.GetGetMethod();
if (getter == null) return false;
result = getter.Invoke(_subject, null);
return true;
}
}

And finally the unit test method:




[TestMethod]
public void Simple_Data_Test()
{
// ... setup the test, controller and query
var data = controller.JsonData(query).Data;
var rowCnt = AnonymusDynamicGetWrapper.Create(data).total_row_cnt
Assert.AreEqual(25, rowCnt);
}

Feb 4, 2011

Obfuscated Hello World CodeGolf

 

Finally the codegolf Stackexchange site is in beta. So I decided to give it a try, as I found this nice codegolf:

golf

So…. Behold my solution with JavaScript:

javascript:(_=(_=[][(f=!!(_='')+_)[3]+(b=({}+_)[1])+($=(c=(d=!_+_)[1])+d[0])])())[f[1]+'l'+(a=d[3])+$]("H"+a+'ll'+b+' W'+b+c+'ld');

Feel free to try it out. Just paste it in your browser's address bar and let it do the magic.


Well if you would like to know how it works I suggest you read this blog post first (I've actually shared it in my Google Reader feed a month back, so you might have already seen it). The script uses the same principle to acquire the sort() function (and consequently the window object and alert() function) as described there. I also found this nice video that was very helpful.


Good fight, good night :)

Feb 3, 2011

jQuery.validation breaks jQuery 1.5 ajax API

Today I found out (the hard way) that the use of the jQuery.validation plugin breaks the jQuery.ajax API. Since the Asp.net MVC 3 uses jQuery.validation for its unobtrusive validation it is included in the default project template. You can imagine my surprise when I updated jQuery to v1.5, and my heavy ajaxified MVC page stopped working correctly. Every ajax request contained an parseerror with an error message stating that the callback jQuery[some random string] was not called. I tried to fiddle with the ajax settings for JSONP (namely jsonp and jsonpCallback), but no matter how I set them, the error was still present.

error_example
Error message

So I started digging around, trying to replicate the problem. When I ran simple html pages $.ajax worked as expected. Then I started to gradually test all the jQuery plugins and found out that the plugin causing the error was jQuery.validation. So here is my reproduction and a simple workaround (the whole project is available here):

The controller:

using System.Linq;
using System.Web.Mvc;

public partial class DefaultController : Controller
{
  private static readonly int[] numbers = Enumerable.Range(1, 10).ToArray();

  public virtual ActionResult Index()
  {
    return View();
  }

  [HttpPost]
  [ValidateAntiForgeryToken]
  public virtual JsonResult SimpleArray(int id)
  {
    return Json(numbers.Concat(new [] { id }));
  }
}

The view:

@{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
  <script src="/Scripts/jquery-1.5.js" type="text/javascript"></script>
  <script src="/Scripts/jquery.validate.js" type="text/javascript"></script>
</head>
  <body>
  <script type="text/javascript">
    $(function () {
      $('a').click(function (e) {
        var req = $.ajax({
            url: '@Url.Action(MVC.Default.SimpleArray())',
            type: 'POST',
            data: $('form').serializeArray(),
            dataType: 'json'
        });
        req.success(function (response, status, xhr) { alert('Success: ' + response); });
        req.error(function (xhr, error, msg) { alert('Error "' + error + '": ' + msg); });
      });
    });
  </script>
  <a href="javascript:void(0);">Do request</a>
  <form action="#">
    <input type="hidden" value="-1" name="id" />
    @Html.AntiForgeryToken()
  </form>
</body>
</html>

The workaround:

$(function () {
$.ajaxSettings.cache = false;
$.ajaxSettings.jsonp = undefined;
$.ajaxSettings.jsonpCallback = undefined;
})


The cause of the problem is this line of JavaScript in jQuery.validate.js, that overrides the settings you pass into the $.ajax call with all the default ones (and jQuery.ajaxSettings defaults to { jsonp: "callback", jsonpCallback: function() {...}}):


// create settings for compatibility with ajaxSetup 
settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));

Cheers!