TFS addin for Outlook TaskConnect released!

TaskConnect connects Outlook with issue tracking systems in a very cool way. So far there is support for TFS (2008, 2010) and Redmine.

This is how TaskConect looks inside Outlook:



It has many useful concepts making you deal with your tasks in no time. Be sure to check out the entirely new website.

Posted by Martin Konicek on 12:08 AM 2 comments

Scripting in Scala

Imagine we have a long text file, for example:

'CHINESE' : 'zh',
'DUTCH': 'nl',  
'ENGLISH' : 'en',
'SPANISH' : 'es',

And we want to turn it into this:

'zh' : 'Chinese',
'nl' : 'Dutch',  
'en' : 'English',
'es' : 'Spanish',

What we want to do is very simple: "Swap the two parts on every line!", and I believe it should be this simple also in code. Let's see how it looks in Scala:

import scala.io.Source

val lineRegex = "\\s+'(.+)'.*'(.+)'.*".r

for(line <- Source.stdin.getLines) {
   val lineRegex(name, code) = line
   println("'%s': '%s'," format (code, name.toLowerCase.capitalize))
}

That's 5 lines including the import, and the code is readable. Now we can run:

cat languages.txt | scala ourScript.scala > output.txt

That's it.

Btw, let's look at at the options we had for solving the problem:
  1. We don't want to be writing code in Java, C++ or C# and actually compiling an executable. Also you can imagine that the code in any of these languages would be overly complicated.
  2. OK, so we definitely should use a scripting language. What options do we have?
    • sed, awk, perl - Learn a (cryptic) language just for the purposes of scripting? No thanks.
    • Python, F#, Scala - All these languages have an amazing property that while you are already building your applications in them, you can use them for writing quick scripts. Scala is just elegant and more innovative than F# or Python. For a deeper look how the magic with lineRegex works, see this. If unfamiliar with Scala, here is a quick overview.

Posted by Martin Konicek on 4:02 PM 2 comments

Posted by Martin Konicek on 6:46 PM 5 comments

New blogposts about programming Outlook add-ins

I published two new blogposts on the website of our add-in for Outlook called TaskConnect:
Adding custom data to Outlook emails
Searching emails from an Outlook add-in

Knowing the information published there before developing TaskConnect would definitely help me a lot so I'm sharing it. I hope you will also find it useful.

Posted by Martin Konicek on 12:00 AM 5 comments

TFS addin for Outlook TaskConnect goes live!

You can download the first beta of TaskConnect now. I've been working on this for the last year with a team of cool guys in Prague.
TaskConnect is quite unique as it integrates TFS into Outlook in a new, clever way:

  • TaskConnect is a full-fledged TFS client with fulltext search field at your fingertips right in Outlook
  • Work items can be attached to emails: when you are discussing a work item with someone, the work item is visible right next to the email throughout your whole conversation. You can of course edit it right from Outlook.
  • Saving your time is absolutely the primary goal - speed of use is just incomparable to any existing TFS client
We think this is such a good idea that it would be silly just to support TFS. So in the future you can expect Outlook integration of many popular issue tracking systems. We also have a ton of ideas for the future and we are looking forward to your feedback and ideas.

Posted by Martin Konicek on 4:50 PM 0 comments

C# 4 delegates contravariance

A little quiz.

Given the following two delegates:

delegate void EventHandler(object sender, EventArgs e);

 

delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);


Does the following code compile?

void propertyHandler(object sender, PropertyChangedEventArgs e)

{ }

 

EventHandler handler = propertyHandler;






Did you answer "YES, because PropertyChangedEventHandler IS an EventHandler"?






Unfortunately, the answer is no. Imagine how would the following code work:

handler(this, new EventArgs());


How could just EventArgs be passed to propertyHandler, which expects PropertyChangedEventArgs?

Actually, the exact opposite is correct in C# 4:

void handler(object sender, EventArgs e)

{ }

 

PropertyChangedEventHandler propertyHandler = handler;


Then, calling

propertyHandler(this, new PropertyChangedEventArgs("Name"))


is perfectly ok, because the handler just sees passed PropertyChangedEventArgs as EventArgs.

So the conclusion is: you can handle specialized events using less specialized handlers (you can handle eg. PropertyChanged event using just an EventHandler).

For more info, see C# delegates on msdn.

Posted by Martin Konicek on 4:58 AM 0 comments

Implementation of anonymous delegates in C#

What is the output of the following program?

int x = 5;

Action action = (() => { Console.WriteLine(x); });

x = 6;

action();



The output is of course 6, because delegates capture references to outer variables.

So how is this implemented in the compiler?
The compiler rewrites the code above to something like this:

Scope s = new Scope();

scope.x = 5;

Action action = (scope);

scope.x = 6;

scope.Call();


and defines the Scope class like this:

private sealed class Scope

{

    public int x;

 

    public Scope();

    public void Call()

    {

        Console.WriteLine(this.x);

    }

}



As we would expect, the is no way to create a reference to eg. an int in IL, so this is solved naturally - the int is wrapped inside Scope class and all accesses are done through the wrapper.
The wrapper also defines the Call method, which is exactly the body of the anonymous delegate.

Actually, the compiler generated name for our Scope class is "<>__DisplayClass1", and the Call method is named "<Main>b__0".

For a little more complex example, see this post on stackoverflow.

Posted by Martin Konicek on 4:18 PM 0 comments