Sunday, July 27, 2008

This is part 2 of C# 3.0: From "C++" to "Ruby" Family - Part I. In this part, I will brief the remaining part of "Generics".
Applying your constraints on Generic


What is the real usage of allowing any type into my generic method or in class. We know that TransferAccount() method relies on bank account which could be either savings, current, etc. It is not sensible to allow any type of objects as parameter. In such case, you can apply constraint on Generic by C#2.0 new keyword "where" as:

  • generic type should be derived from this base class or should implement this interface (where T : base-class-name interface-name)

  • generic type should be a none other than class for example struct (where T:class)

  • generic type should have default constructor (where T : new())

For example, let us refactor our previous code like:

public TAccount CreateInstance<TAccount>(long accountNumber) where T : Account
{
// create either savings, current account instance based on account number
}

The above code apply the constraint "only allow types derived from "Account" base class" into CreateInstance.


Anonymous Methods followed by Lamda Expression:

I had been unbalanced with OOP/procedural and functional programming concepts year back, because of the mix of these two concepts will make programming more tasteful and better. Because of this reason only, I love Ruby and JavaScript programming (of course C# is mixed in the life of a programmer).
One nice thing about functional programming is "closure" methods or "lamda expression".

Let us see our famous C# delegate:

delegate int Calculator(int a, int b);

static void Main(string[] args)
{
Calculator add = Add;
Console.WriteLine(add(2, 3));
Console.ReadLine();
}

public static int Add(int x, int y)
{
return x + y;
}

In the above code, I have declared a delegate "Calculator" and used this for "Add" method. As per "Not every theoretical can be used in practical", in most of the situation, we are in a position to define a delegate and then we need to apply one or more methods one time only like the above example. In such case, defining a delegate and then defining method for that delegate results less "beautiful code". C# 2.0 introduced "anonymous methods" eliminates and save developer productivity and the code. By this,
Calculator add = delegate(int x, int y) { return x + y; };
Console.WriteLine(add(2, 3));
Without defining "Add" method, we can define anonymous methods.

Why Lamda Expression?

This is in place of anonymous delegate instance . See the below code:
Calculator add = (int x, int y) => { return x + y; };
Console.WriteLine(add(2, 3));
Visually whats the different? "delegate" has been removed and "=>" introduced. Otherwise, the same in visual perspective. But under C#'s regime, lamda expression is something different from "anonymous methods". (For me, it provides functional programming feature.)
The code within {...} denotes an expression tree of type Expression<T>. This allows the lamda expression to be interpreted at runtime and not in compile time. Greatna.!

Thursday, July 10, 2008

Download Example Source Code

This is part 2 of WF: Exception Handling with State Machine Workflow.

Solution Sample
In the previous article we discussed issues when handling exception in state machine workflow and specified that we can resolve the issue by using CallExternalMethod activity. Last time, I've explained the issue by giving RoseIsRose sample. In this solution, I've two project, one is state machine workflow library called RoseIsRoseWorkflow and another one is console application which is host for workflow named RoseIsRoseConsole.

The objective is if any exception happens in the state machine workflow, the workflow should propagate it to host.

For sake of simplicity, the workflow in the library named RoseWorkflow has only one state named "BudState". This state has only one EventDrivenActivity called "onPluckFlowersEvent". It has one HandleExternalEvent named "handlePluckFlowersEvent".



The code for above workflow's InterfaceType is following:


using System;
using System.Workflow.Activities;

namespace RoseIsRoseWorkflow
{
[ExternalDataExchange]
public interface IRoseWorkflowService
{
event EventHandler PluckFlowers;
void DelegateException(Exception ex);
void RaisePluckFlowersEvent(Guid instanceId);
}
}


What about the fault handlers and what we need to redesign for propagating exception to host?

In IRoseWorkflowService, I have declared a method "DelegateException" which will be called by "CallExternalMethod" from the workflow. The "RaisePluckFlowersEvent" is used by host to invoke "PluckFlowers" event in IRoseWorkflowService which is actually handled at RoseWorkflow.



Before "callExternalMethodActivity1", I have used one code handler named "onPluckFlowersEventFaultCodeHandler" for just displaying debug message. The code behind of RoseWorkflow.cs is


namespace RoseIsRoseWorkflow
{
public sealed partial class RoseWorkflow : StateMachineWorkflowActivity
{
private object _sender;
public object Sender
{
get { return _sender; }
set { _sender = value; }
}

private Exception _delegatedException;
public Exception DelegatedException
{
get { return _delegatedException; }
set { _delegatedException = value; }
}

private ExternalDataEventArgs _eventArgs;
public ExternalDataEventArgs EventArgs
{
get { return _eventArgs; }
set { _eventArgs = value; }
}

public RoseWorkflow()
{
InitializeComponent();
}

private void handlePluckFlowersEvent_Invoked(object sender, ExternalDataEventArgs e)
{
_delegatedException = new Exception("In this stage, you cannot pluck flowers");
throw _delegatedException;
}

private void onPluckFlowersEventFaultCodeHandler_ExecuteCode(object sender, EventArgs e)
{
FaultHandlerActivity faultHandler = ((Activity)sender).Parent as FaultHandlerActivity;
Console.WriteLine("Handle exception in workflow itself. Details: {0}",
faultHandler.Fault.Message);
}
}
}


At the host side, I have implemented part of IRoseWorkflowService in RoseWorkflowService.cs:



using System;
using System.Workflow.Activities;
using RoseIsRoseWorkflow;

namespace RoseIsRoseConsole
{
[Serializable]
public class RoseWorkflowService : IRoseWorkflowService
{
#region IRoseWorkflowService Members

public event EventHandler PluckFlowers;
public Exception DelegatedException;

public void DelegateException(Exception ex)
{
DelegatedException = ex;
}

public void RaisePluckFlowersEvent(Guid instanceId)
{
if (PluckFlowers != null)
PluckFlowers(null, new ExternalDataEventArgs(instanceId));
while (DelegatedException == null) ;
Console.WriteLine("Externally handled exception '{0}'. Details: {1}",
DelegatedException.GetType().Name, DelegatedException.Message);
DelegatedException = null;
}

#endregion
}
}


Note that "DelegateException" will be called by workflow. Whenever, it is getting called it assigned the exception details to the public field "DelegatedException". In the "RaisePluckFlowersEvent" method, once it raised "PluckFlowers" event, the method going on a while until the "DelegatedException" is null. After that, it just handle the exception (either rethrow it to calling client or logged at host place).

The Program.cs is


namespace RoseIsRoseConsole
{
class Program
{
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};

ExternalDataExchangeService dataExchange = new ExternalDataExchangeService();
workflowRuntime.AddService(dataExchange);
RoseWorkflowService roseWorkflowService = new RoseWorkflowService();
dataExchange.AddService(roseWorkflowService);

WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(RoseWorkflow));
instance.Start();

roseWorkflowService.PluckFlowers += new EventHandler(roseWorkflowService_PluckFlowers);
roseWorkflowService.RaisePluckFlowersEvent(instance.InstanceId);
waitHandle.WaitOne();
}
}

static void roseWorkflowService_PluckFlowers(object sender, ExternalDataEventArgs e)
{
Console.WriteLine("Handling PluckFlowers event");
}
}
}


The output:

Handling PluckFlowers event
Handle exception in workflow itself. Details: In this stage, you cannot pluck flowers
Externally handled exception 'Exception'. Details: In this stage, you cannot pluck flowers


For further reference, download the example project.

Thursday, July 03, 2008

This is part 2 of Event Watch: Moblin - Intel's Mobile Flavour Part 3.

After getting all the components, I could start Xephyr on the MIC device target terminal window. But, it did not keep me smile. The Xephyr window was broken immediately and I got the following error


(T: HelloMoblinApp)root@sheik-laptop:/# ...
Xlib: connection to ":0.0" refused by server


It was my mistake that I forgot to install LibOSSO library. Then I installed it on the target terminal.


(T: HelloMoblinApp)root@sheik-laptop:/# apt-get install libosso-dev


After that I started Xephyr, this time it throws


(T: HelloMoblinApp)root@sheik-laptop:/# ume-xephyr-start
Setting screen resolution to 1024x600
DISPLAY already set to :0.0
Starting dbus
* system message bus already started; not starting.
Starting UI in Xephyr

Extended Input Devices not yet supported. Impelement it at line 625 in ../../../../hw/kdrive/src/kinput.c
Could not init font path element /usr/share/fonts/X11/cyrillic, removing from list!
Could not init font path element /var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType, removing from list!
X connection to :0.0 broken (explicit kill or server shutdown).
xinit: connection to X server lost.


Then I've gone thorugh some mail-list and I found a workaround at http://www.moblin.org/archives/html/dev/2008-04/msg00101.html. It said that use


# pkill gconfd

It kills parent's gconfd and uses target environment's gconfd. After that Xephyr started successfully but it throws same warning message, just skip that.

After that I was trying to compile and execute the given hello-world-1.-c at Moblin.org site. However, I am not able to compile, it says


(T: HelloMoblinApp)root@sheik-laptop:/usr/src/hello# gcc -o hello-world-1 hello-world-1.c `pkg-config --cflags --libs gtk+-2.0`
Package gtk+-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtk+-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtk+-2.0' found
-su: gcc: command not found

Ha ha interesting, I was not in the situation whether gtk+-2.0 is already there in my Ubuntu or not. I just given


(T: HelloMoblinApp)root@sheik-laptop:/# sudo apt-get install libgtk2.0-dev


After that you have to install gcc on the target terminal

(T: HelloMoblinApp)root@sheik-laptop:/# sudo apt-get install gcc


After that I have successfully executed the hello world app.

Thank God.

One good thing is that the packages "gcc" and "libgtk2.0-dev" are got from host app only. It is nice thing about Moblin.

Let us see with more code on Moblin.