Archive

Archive for the ‘.NET’ Category

Revisit Dynamic Event Handler in .NET

July 11th, 2012 Comments off

A while ago I blogged about how to build a catch-all handler for .NET events and delegates. That solution uses LCG to generate CIL for the dynamic delegate. The latest version of Fasterflect however uses Expression Trees to generate the dynamic delegate. So I thought I would post the new solution here for completeness.

Training screen casts (in Vietnamese) about C#, ASP.NET MVC, LINQ and Combres

August 15th, 2011 7 comments

The series of MVC/C#/LINQ/Combres screen-casts (in Vietnamese) I produced for Microsoft Vietnam a while a go. Microsoft Vietnam recently allowed CiOne to distribute on their website so that everyone can access for free.

C# Training for Microsoft Customers

June 16th, 2011 1 comment

Slides for the C# training I conducted for Microsoft’s customers in Ho Chi Minh city on June 9th 2011. The training covered C# 3.0, LINQ, C# 4.0 and Dynamic Binding.

Some pictures of the training
Me

Me

Me

A catch-all .NET delegate and event handler

April 15th, 2011 Comments off

In a current project, I need to build a catch-all handler which could be used to wired to any static or instance delegate and event regardless of the actual delegate/event type.

For example, given the following definitions:

    
private delegate int Op(int i);
private delegate int BinaryOp(int i, int j);
class Test
{
    public Op OpDelegate;
    public event BinaryOp BinaryEvent;
}

I want to be able to write code like this:

    
obj.AddHandler("OpDelegate", args => (int)args[0] * (int)args[0]);
obj.AddHandler("BinaryEvent", args => (int)args[0] + (int)args[1]);

In the above code segment, code>obj is an instance of the Test class. AddHandler should be an extension method for object class. The parameters include the name of the delegate or event and a catch-all handler of type Func<object[], object> and this handler might have been bound to some target. In addition, the code in question mustn't need to know about the actual type of obj at compile time nor does it need to know about the actual signature of the delegate and event being wired.

What AddHandler needs to do is creating some delegate matching the definition of the delegate/event being wired and have that delegate forward the call to the Func<object[], object> argument. That calls for a bit of code generation to build a delegate instance from a runtime generated method definition (which will have its signature match the delegate/event being wired). Like when developing Fasterflect, I opt for CIL generation.

The code for the solution is below. I will incorporate it into Fasterflect as an add-on service. Note that it makes use the EmitHelper class which could be found here.

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using Emitter;

public static class DynamicHandler
{
    public static Type AddHandler(this Type targetType, string fieldName,
        Func<object[], object> func)
    {
        return InternalAddHandler(targetType, fieldName, func, null, true);
    }

    public static Type AssignHandler(this Type targetType, string fieldName,
        Func<object[], object> func)
    {
        return InternalAddHandler(targetType, fieldName, func, null, false);
    }

    public static Type AddHandler(this object target, string fieldName,
        Func<object[], object> func)
    {
        return InternalAddHandler(target.GetType(), fieldName, func, target, true);
    }

    public static Type AssignHandler(this object target, string fieldName,
        Func<object[], object> func)
    {
        return InternalAddHandler(target.GetType(), fieldName, func, target, false);
    }

    private static Type InternalAddHandler(Type targetType, string fieldName,
        Func<object[], object> func, object target, bool combine)
    {
        Type delegateType;
        var eventInfo = targetType.GetEvent(fieldName);
        if (eventInfo != null && !combine)
            throw new ArgumentException("AssignHandler cannot be used for event type");

        if (eventInfo != null)
        {
            delegateType = eventInfo.EventHandlerType;
            var dynamicHandler = BuildDynamicHandler(targetType, delegateType, func);
            eventInfo.GetAddMethod().Invoke(target, new Object[] {dynamicHandler});
        }
        else
        {
            var fieldInfo = targetType.Field(fieldName,
                                                target == null
                                                    ? Flags.StaticAnyVisibility
                                                    : Flags.InstanceAnyVisibility);
            var field = !combine ? null : target == null
                                            ? (Delegate) fieldInfo.Get()
                                            : (Delegate) fieldInfo.Get(target);
            delegateType = fieldInfo.FieldType;
            var dynamicHandler = BuildDynamicHandler(targetType, delegateType, func);
            field = field == null
                        ? dynamicHandler
                        : Delegate.Combine(field, dynamicHandler);
            (target ?? targetType).SetFieldValue(fieldName, field);
        }
        return delegateType;
    }

    public static Delegate BuildDynamicHandler(this Type delegateOwnerType, Type delegateType, 
        Func<object[], object> func)
    {
        MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
        Type returnType = invokeMethod.ReturnType;
        bool hasReturnType = returnType != Constants.VoidType;
        var paramTypes = invokeMethod.GetParameters().Select(p => p.ParameterType).ToArray();
        var dynamicMethod = new DynamicMethod("add_handler",
                                                hasReturnType ? returnType : null, 
                                                new [] {typeof(Invoker)}.Concat(paramTypes).ToArray(),
                                                delegateOwnerType);
        var il = new EmitHelper(dynamicMethod.GetILGenerator());
        il.ldarg_0.end(); // <this>
        il.DeclareLocal(typeof(object[])); 
        il.ldc_i4(paramTypes.Length); // <this> <length>
        il.newarr(typeof(object)); // <this> <arr>
        il.stloc_0.end(); // <this>
        for (int i = 0; i < paramTypes.Length; i++)
        {
            il.ldloc_0 // <this> <arr>
                .ldc_i4(i) // <this> <arr> <i>
                .ldarg(i + 1) // <this> <arr> <i> <arg_i+1>
                .boxIfValueType(paramTypes[i]) // <this> <arr> <i> <boxed_if_value:arg_i+1>
                .stelem_ref.end(); // <this> 
        }
        il.ldloc_0.end(); // <this> <arr>
        il.callvirt(Invoker.InvokeMethodInfo); // <ret>
        if (hasReturnType)
            il.unbox_any(returnType).ret();
        else
            il.pop.ret();
        return dynamicMethod.CreateDelegate(delegateType, new Invoker(func));
    }

    public class Invoker
    {
        public static readonly MethodInfo InvokeMethodInfo =
            typeof(Invoker).Method("Invoke", Flags.InstanceAnyVisibility);
        private readonly Func<object[], object> func;

        public Invoker(Func<object[], object> func)
        {
            this.func = func;
        }

        public object Invoke(object[] args)
        {
            return func(args);
        }
    }
}
Categories: .NET Tags: , , ,

I’m a Microsoft MVP, again

April 4th, 2011 6 comments

I’ve just got news from Microsoft that I am, once again, a Microsoft MVP in ASP.NET/IIS (formerly ASP/ASP.NET).  This is exciting news.  A big thanks to all Microsoft employees and community members who have worked with me in various projects during the past year.

MVP-h-550x222

Categories: .NET Tags: ,

Microsoft Technology Conference in Hanoi

March 19th, 2011 2 comments

I had a chance to speak about HTML5 in IE9 and ASP.NET MVC 3 at the Microsoft Technology Conference in Hanoi, Vietnam on Thursday Mar 17th 2011.  The event was supposed to attract 200 audiences.  However the suddenly cold weather and non-stop rain (more later) probably made a few dozens not show up.

This trip to Hanoi was very memorable in many ways.  First, I met and had conversations with many interesting people and learned many things from other speakers (agile development with Scrum & Kanban, BI in SharePoint 2010, distributed caching in practice etc.)  It’s a pity that I had to leave early to catch the flight (which was eventually delayed for as much as 2.5 hours) so I missed a couple of late sessions.

Second, the whole trip itself contains full of surprises.  Both departing and coming back flights were delayed 1 and 2.5 hours respectively, leaving me exhausted in the airports (thanks VNA!).  And then the weather.  In Ho Chi Minh, it was hot like 30 C degree something.  In Hanoi, it was 9 C the moment the plane arrived and remained that cold during the whole time.  I ended up putting on as many clothing as I brought with me to avoid catching a cold (and sounding like a duck during my speeches).  Additionally, it was raining all the time and I was basically on taxi every time I walked out of a building. (And should I mention that there were 2 cab drivers, 1 hotel receptionist and 1 flightmate mistook me for being foreigner and started speaking English to me!)

Slides and code can be found below.  There are a few pictures (of me and some other speakers) taken by a friend of mine.  I hope to receive pictures from Microsoft as well.

ASP.NET MVC 3

View more presentations from Buu Nguyen.
Download code demo here.

Me

Me

Me

Magnus Stråle

Keynote

ASP.NET MVC 2 Cookbook

February 15th, 2011 Comments off

One of the books of which I was the technical reviewer was published: ASP.NET MVC 2 Cookbook. Access to the link to find out more about the book.

aspnetmvccookbook

Categories: .NET Tags: ,

C# 4.0 Dynamic Binding at BarCamp Saigon 2010

December 13th, 2010 Comments off

I hugely enjoyed BarCamp Saigon 2010 which took place yesterday at RMIT University.  Learned a lot of things and met great people.

Below is the slidedeck I used for my session.  Source code is here.

ASP.NET MVC 2.0 Training

November 1st, 2010 2 comments

Last week, I conducted a training for customers of Microsoft about ASP.NET MVC 2. The training took place at Microsoft’s office in Ho Chi Minh city. The slides used for the training is below.

Handle all uncaught exceptions thrown when using Task Parallel Library (take 2)

May 7th, 2010 3 comments

A couple of days ago I posted a solution to handle all uncaught exceptions when using TPL. I’ve found a better way to do that, making use of task continuation. The class ThreadFactory below exposes the Error event which can be subscribed by a top-level handler and provides methods to start a task attached with proper continuation.

internal class ThreadFactory
{
    public delegate void TaskError(Task task, Exception error);

    public static readonly ThreadFactory Instance = new ThreadFactory();

    private ThreadFactory() {}

    public event TaskError Error;

    public void InvokeError(Task task, Exception error)
    {
        TaskError handler = Error;
        if (handler != null) handler(task, error);
    }

    public void Start(Action action)
    {
        var task = new Task(action);
        Start(task);
    }

    public void Start(Action action, TaskCreationOptions options)
    {
        var task = new Task(action, options);
        Start(task);
    }

    private void Start(Task task)
    {
        task.ContinueWith(t => InvokeError(t, t.Exception.InnerException),
                            TaskContinuationOptions.OnlyOnFaulted |
                            TaskContinuationOptions.ExecuteSynchronously);
        task.Start();
    }
}
Categories: .NET Tags: , , ,