Fun with Func, lambdas and closures

I had a need to encapsulate a method and execute it in a loop (ideally by an external component) for rudimentary retry logic.  I further didn’t want to be confined to a specific method signature.  In other words, I wanted a class to be able to call a function generically without having to know the method signature but still have a consistent return type.

Turns out, it was pretty easy to pull off.  Define a Func<T> as your delegate for the routine you want to call.  Then, define another Func<T> that is assigned to a lambda (or you could use an anonymous method) which calls the Func<T> previously specified.  You’ve just created a closure, so now you can toss that little Gem off to some class that accepts the signature of the second Func<T> and loop around, executing that function over and over.  I haven’t cracked the code open yet in Reflector, but my understanding is this all gets boiled down to compiler slight of hand, creating types for all this, and I believe stack state is pushed onto the heap (along with the *this* pointer).

Example (toss in a console app):

class Program

    {

        private string id;

 

        static void Main(string[] args)

        {

            Program program = new Program();

            program.DoStuff();

 

            Program program2 = new Program();

            program2.DoStuff();

        }

 

        private void DoStuff()

        {

            this.id = Guid.NewGuid().ToString();

 

            Func<string, string> myFunction = this.Echo;

            Func<string> myClosure = () => myFunction(“Hey there!”);

 

            string[] messages = this.RunThreeTimes(myClosure).Split(“,”.ToCharArray());

 

            foreach (string message in messages)

            {

                Console.WriteLine(message);

            }

 

        }

 

        private string Echo(string message)

        {

            return string.Concat(message, this.id);

        }

 

        private string RunThreeTimes(Func<string> bundleOfJoy)

        {

            StringBuilder sb = new StringBuilder();

 

            for (int i = 0; i < 3; i++)

            {

                sb.Append(bundleOfJoy.Invoke() + “,”);

            }

 

            return sb.ToString().TrimEnd(“,”.ToCharArray());

 

        }

    }

 

 

Asp.net extender to provide client-side databinding (a pet project)

I’m just playing around, extending the “Markupbuilder” code in this article (I mentioned this in this blog entry).  Its a complete code mess and I’d need to take it light years further (and clean up the naming of stuff) to actually do anything w/it (although, i’m slightly considering).  Anyhow, I’ve got the concept baked down into a asp.net server control you just drop on your form and go with minimal coding required on the developer’s part. The control wires up the client-side event handler with the [wcf | asmx] web service via Asp.Net Ajax’s client-side Sys.Net.WebServiceProxy object.  It also provides lots of events to hook into, as well as all the goodness in Dino’s article (header/item/footer templates, and the formatting event).  His code didn’t work in FireFox with the way <xml/> tags were used.  There were ways to make those work, but I wrap the data in  <!–[CDATA tags.  Steps to use are:

1.  Drop a “DatabinderExtender” control on your form and set properties. Example of markup:

<%@ Register TagPrefix=”cc” Namespace=”ClientsideDatabinding” %>

<cc:DatabinderExtender
ID=”DataBinder1″
runat=”server” ScriptPath=”Javascript/ClientDataBinder.js”
TargetControlID=”peepsContainer” OnBeforeInvoke=”onBeforeInvoke” InvocationElementClientId=”button1″ InvocationEventName=”click”
ServiceProxyName=”CrazyServices.IService” ServiceProxyMethodName=”GetPeeps” ServiceProxyParameterRetrieverDelegateName=”gatherParams” HeaderTemplateClientId=”headerTemplate”
ItemTemplateClientId=”itemTemplate” FooterTemplateClientId=”footerTemplate” FormatterClientDelegateName=”makeDataPretty”
ErrorFunctionClientDelegateName=”displayPeepsError” NoDataClientDelegateName=”noDataFound” />

2.  You’ll note the various events that you can trap on your client.  For example, use “ServiceProxyParameterRetrieverDelegateName” (crapy name) for the method on your form to set the parameters prior to the Ajax call.  It receives a javascript dictionary of parameter info for whatever service you configured on the DatabinderExtender (I use reflection on the server to inspect the configured Service and Method to snag information about the parameters, and bake that into the client-side control).  For example, here is the “gatherParams” method assigned as the event handler:

function gatherParams(paramsDictionary) {

      // Set via integer index
      for(var i=0;i<paramsDictionary.length;i++){

        if(paramsDictionary[i].name=="ageRangeLow")
        {
          paramsDictionary[i].value = parseInt($get('txtAgeLow').value);
        }

        // .....(others...)
      }

      // -- or --

      // Set via string index
      paramsDictionary["ageRangeLow"].value = parseInt($get('txtAgeLow').value);
      paramsDictionary["ageRangeHigh"].value = parseInt($get('txtAgeHigh').value);
      paramsDictionary["namePattern"].value = $get('txtName').value;

    }

3.  Other events allow for canceling the operation, formatting the results, or handling a scenario where no data was returned.

4.  You also need to define your container (often a <div/> or similar), and the markup for the “Header”, “Item”, and “Footer” templates such as (this is all similar to how Dino had it in his article, except the use of [CDATA[ directives):

<span id=”headerTemplate” style=”visibility:hidden;“><!–[CDATA[<table cellpadding=”3″><thead><tr><th>Name</th><th>Age</th></tr></thead>]]–></span>

  <span id=”itemTemplate” style=”visibility:hidden;“><!–[CDATA[<tr><td>#Name</td><td>#Age</td></tr>]]–></span>

  <span id=”footerTemplate” style=”visibility:hidden; ><!–[CDATA[</table>]]–></span>

For the curious, here is the cheeseball code I threw together this evening which builds that client-side dictionary of parameter info:

private string AddParamsDefinitionDictionary()
    {
      StringBuilder result = new StringBuilder();
      result.AppendLine("function (){");
      result.AppendLine("var result = [];");

      Type type = Type.GetType(this.ServiceProxyName);
      MethodInfo methodInfo = type.GetMethod(this.ServiceProxyMethodName);

      ParameterInfo[] parameters = methodInfo.GetParameters();

      if (parameters == null || parameters.Count() <= 0)
      {
        return null;
      }

      const string ITEM_TEMPLATE = @"result[""PARAM_NAME""] =           
        eval('({""name"":""PARAM_NAME"",""value"":"""",           ""type"":""TYPE_NAME""})');";
      string item = string.Empty;
      string typeName = string.Empty;

      int counter = 0;

      foreach (ParameterInfo parameterInfo in parameters)
      {
        item = ITEM_TEMPLATE.Replace("PARAM_NAME", parameterInfo.Name);
        typeName = GetTypeName(parameterInfo);
        item = item.Replace("TYPE_NAME", typeName);
        result.AppendLine(item);
        result.AppendLine(string.Format("result[{0}] = {1}", counter.ToString(), item));
        counter++;
      }

      result.AppendLine("return result;");
      result.AppendLine("}");

      return result.ToString();
    }
 private string GetTypeName(ParameterInfo parameterInfo)
    {
      string result = string.Empty;

      if (parameterInfo.ParameterType.Name.Contains(typeof(short).Name) ||          
                 parameterInfo.ParameterType.Name.Contains(typeof(Int32).Name)
                 || parameterInfo.ParameterType.Name.Contains(typeof(long).Name))
      {
        result = "number";
      }
      else if (parameterInfo.ParameterType.Name.Contains(typeof(bool).Name))
      {
        result = "boolean";
      }
      else if (parameterInfo.ParameterType.Name.Contains(typeof(object).Name))
      {
        result = "object";
      }
      else
      {
        result = "string";
      }

      return result;
    }

Well, anyhow, just something i’m playing around with.  It helps to build something to make some of the concepts sink in further.  -J

WDSync…a perfect example of how not to design your UI

I have this great external hard drive from Western Digital.  It rocks as a clean, highly-portable drive.  However, then it has this software that is supposed to help with synchronizing and protecting files.  The thing is miserable to work with as every time you make a selection in their UI, if the folder you are configuring is of any size, the UI freezes up like this:

wdsuck

 

Users expect that you make setting and configuration changes, *then* click the “go forth and do that” button and at that point expect to wait not before.  Great example of how not to design a UI.

the value of “hands on the keyboard”

I’m realizing I’ve been reading up a fair bit on technology, but not actually *writing code* to the degree [I find] necessary.  When not reading the current book, I’m still playing around extending a neat little asp.net client-side databinding class from this article from my homie Dino.  I’ve taken the concept and boiled it down into a Sys.UI.Behavior class, reducing the consumer to a one-liner.  I’ve looked into further breaking that down into a ScriptBehaviorDescriptor but realize that on-demand (like event-based)  situations are a tad under-supported.   I know this stuff is on the way, but its interesting enough.  Seems like one of those little nitches you could bust out some cool code for $15.99 and rack up until the other stuff releases.

In either case, neat to play with.  Client-side stuff is fun, but is’nt it amazing how clunky you feel writing it?  Like 10% of the speed you’d run with server-side code?

 

J