Thursday Night

Paul Betts’s personal website / blog / what-have-you

Archive for the ‘Mono / .NET’ Category

A C# 3.5 pattern – the Accept Block pattern

4 comments

A coworker pointed me towards this blog post as a useful trick to make code read cleaner. I’ve been using this trick in C# for quite some time, as it’s a very fundamental pattern in Ruby programming. In my head I call this the “Accept Block” pattern, but I’m fairly certain its just a syntactic version of an existing pattern (the Strategy pattern?). In some sense, it’s like being able to write your own version of the “using” or “lock” statements.

Here’s the old imperative way you might write some code:

void Foo()
{
    SetupTheDatabase();
    bool ShouldExit = SomeFunctionThatNeedsADatabase();
    TeardownTheDatabase();

    if (ShouldExit)
        return;

    DoOtherStuff();
}

And here’s how you’d rewrite it using the pattern:

void WithEnsureDatabaseIsSetup(Action block)
{
    SetupTheDatabase();
    try {
        block()
    } finally {
        TeardownTheDatabase()// Note: Make sure this doesn’t throw!
    }
}

void Foo()
{
    bool ShouldExit;

    WithEnsureDatabaseIsSetup(() => {
        ShouldExit = SomeFunctionThatNeedsADatabase();
        if (ShouldExit)
            return;
    });

    DoOtherStuff();
}

In my opinion, the 2nd version is better to read, and more importantly, allows you to encapsulate the “setup/teardown” pattern – this way, this block of code is consistent, removes copy-paste errors from writing the same thing over and over again, and is easily updated if you want to do additional work when setting up the database.

But there’s a gotcha!

There’s a bug in the above code though that’s quite subtle, and that has bitten me a few times – the syntax () => { } is defining a closure, an anonymous function who can use variables bound inside its lexical environment (to understand the difference, take a look at that ShouldExit variable – even though it’s not a parameter of the function, we were still able to use it). When you call return, in the original example we will exit Foo() – in the new version, we will exit the closure and still execute DoOtherStuff()! Here’s how we should fix it:

void Foo()
{
    bool ShouldExit;

    WithEnsureDatabaseIsSetup(() => {
        ShouldExit = SomeFunctionThatNeedsADatabase();
    });

    if (ShouldExit)
        return;     // Now we’ll return properly

    DoOtherStuff();
}

Ruby doesn’t have this problem

This is a fundamental pattern in Ruby and built into the language and the runtime, so much so that it has special syntax to make it happen. However in Ruby a “block” is a slightly different syntactic structure than a function, so return will do what you expect:

def Foo(an_array)
    an_array.each { |item|  # This is a block with 1 param
        print item
        return if item > 2  # Actually returns from Foo, not from block
    }
end

Written by Paul Betts

January 10th, 2010 at 9:25 pm

Posted in Mono / .NET, Ruby

Convert a .NET 2.0 DLL to 4.0 (VS2010) without source

2 comments

Converting .NET DLLs to 4.0 by hand is too much work

One of the blockers for upgrading a project to .NET 4.0 is that your old .NET 2.0/3.0/3.5 DLLs will have some difficulty running in .NET 4.0. I’m far too lazy to track down all the 3rd party DLLs like Moq or log4net, download the source, switch the project to 4.0, then recompile the DLL.

Hackery makes life easier

Instead of doing this, for a lot of DLLs, you can get away with roundtripping the DLL using ildasm/ilasm; the only tricky part is changing the assembly references so that they point to .NET 4.0 DLLs instead of the old and busted 2.0 System.* assemblies.

The good news is, I’ve written an IronRuby (or MRI, or JRuby, etc) script to handle this automagically. Here’s how to use it:

How to use:

  1. Download IronRuby from CodePlex (You can use the .NET 4.0 release too, doesn’t matter), and copy it to C:\IronRuby
  2. Download dotnet4ify_dll.rb from my website
  3. Launch the VS Command Prompt (2010) – don’t launch the 2008 one by accident!
  4. set path=%path%;C:\ironruby\bin
  5. mkdir v4dlls
  6. ir dotnet4ify_dll.rb C:\path\to\an\old\assembly.dll .\v4dlls\assembly.dll

Some caveats

  • While I’ve tested this on some pretty complex DLLs (DotNetOpenAuth, ParallelFramework_3_5.dll), it’s definitely in the “Works on My Machine” class of software; in particular, C++/CLI DLLs will probably not work. Embedded resources do still get embedded in the new binary
  • .NET Assemblies get upset if you rename them, so you can’t do something like “ir dotnet4ify_dll.rb foo.dll foo_v4.dll” – just put all your v4 assemblies in a separate directory


Worked for me, but I make no guarantees it won’t replace DLLs with a lolcat

Written by Paul Betts

December 3rd, 2009 at 12:36 am

Posted in Mono / .NET

WPF WebBrowser blank? Check your Airspace!

WPF’s WebBrowser control (and in fact, all native controls, like the Ink controls), have a pretty subtle "gotcha" that made me spend a decent amount of time pulling my hair out. The control would render as all white like it hadn’t loaded the page, yet you can still see Tooltips from the web site as you mouse over the control! Clicking on links still works, scrollbars show up, yet the control is all white! What gives?!

My problem has to do with Airspace; WPF completely discards the concepts that Win32 and WinForms have used to handle UI rendering in the past – all controls in WPF are "Windowless controls"; there is only one HWND allocated to the entire window, whereas Win32 windows typically have many, many HWNDs allocated (one per control). It is this "impedance mismatch" that causes a lot of tricky issues, especially with keyboard/input focus. My Window had the "AllowsTransparency" bool set, so it was being created as a layered window.

The way I solved this in my app was simply to set the AllowsTransparency property of my Window to "false". I suggested that WebBrowser should throw an Exception when it encounters this situation, and the WPF team filed a bug against it for .NET 4.0 so hopefully, this specific gotcha won’t continue into the future.

Written by Paul Betts

November 20th, 2009 at 8:28 pm

Debugging .NET exceptions *without* VS installed using WinDbg

one comment

If your .NET app is crashing on a machine that doesn’t have Visual Studio, here’s the easy way to get the managed exception – people have written way better articles on SOS and WinDbg, but here’s a 10sec overview; even if you have no idea how WinDbg works, often just having the managed exception will give you enough good info, and WinDbg is way easier to install and lightweight than VS.

Install the Debugging Tool for Windows, then spin up WinDbg (or cdb, the command-line version if you’re even more metal). Either attach to a running instance of your program, or start a new one. Run these commands to get started once you get the prompt (if you don’t get the prompt, and you’ve attached, you need to break-in by hitting Ctrl-C):

.sympath srv*http://msdl.microsoft.com/download/symbols
.sympath+ C:\path\to\your\binary\directory
.reload -f
g

Ok, your app is running – one thing that will totally fool you if you’re used to using VS is, if you start the program with WinDbg, your program will break-in immediately once you start it, before any code in your app has run (even the .NET startup code). Now, crash your app; you should’ve been kicked back into the debugger now and back at the prompt, with something like:

CLR exception type: System.Collections.Generic.KeyNotFoundException
    "The given key was not present in the dictionary."
eax=001fe078 ebx=e0434f4d ecx=00000001 edx=00000000 esi=001fe100 edi=005461d8
eip=76c5f35f esp=001fe078 ebp=001fe0c8 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
KERNEL32!RaiseException+0×58:
76c5f35f c9              leave
0:000>

Now, here’s where we get to the real work – to debug .NET framework apps, we need the SOS extension, so we’ll pull that in, then use one of the functions that SOS defines (to see them all, run !help):

0:000> .loadby sos mscorwks
0:000> !printexception

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll –
PDB symbol for mscorwks.dll not loaded
Exception object: 22e0580c
Exception type: System.Collections.Generic.KeyNotFoundException
Message: The given key was not present in the dictionary.
InnerException: [none]

StackTrace (generated):
    SP       IP       Function
    001FE1F4 6BFB480D mscorlib_ni!System.ThrowHelper.ThrowKeyNotFoundException()+0×1d
    001FE1FC 06DF1E20 mscorlib_ni!System.Collections.Generic.Dictionary`2[[LogDebugger.EventGroupingKeys, LogDebugger.Engine],[System.__Canon, mscorlib]].get_Item(LogDebugger.EventGroupingKeys)+0×38
    001FE208 06494B36 LogDebuggerUI!LogDebugger.Ui.FilterEnvironment.[buildhighlightbrushmap]b__e(LogDebugger.LDEvent)+0xe

   [ [ rest of stack trace… ] ]

There’s way more you can do with WinDbg and SOS (it’s the way we debug Windows programs at Microsoft), but this should get anyone who wants a quick way to see an exception the way to do it. Using Mono, you can actually get the exception trace even easier (but you can’t do any debugging), as any app you run via the command line (i.e. via mono ./path/to/app.exe) will print the same information to STDERR.

Written by Paul Betts

May 24th, 2008 at 1:45 pm

Posted in Mono / .NET

No news as of late – but Inkscape now has XAML

one comment

Sorry this blog has been dead lately, I posted a rather depressing article but Wordpress ate it, perhaps it was fate (or its stop being so whiny alarm kicked in). The 2-second summary is, I don’t have many people around but it’s my own damn fault. Ok, now that we’ve got that out of the way, I’ve been working on learning RSpec/TDD in Ruby at home, and at work I’m doing cool WPF stuff (but no TDD, because I hate VS’s test framework support).

Here’s a small news item that got me interested though, via Jon Galloway. The latest versions of Inkscape now export XAML directly, which is great for me because I don’t have an Illustrator license at work (apparently it’s a “competitive product”), and I really don’t jive with Expression Design; then again, I don’t jive with Illustrator either for that matter, but I’d consider forcing myself to learn it because it’s the industry standard. Now, I can easily convert SVGs or bitmaps via VectorMagic into XAML that I can put into my project.

Written by Paul Betts

January 14th, 2008 at 12:29 pm

Posted in Microsoft, Mono / .NET

Seriously cool – NStatic solves linear equations

Equation Solving with static code analysis

NStatic sees the assertions, then determines the only way that this function can execute is via setting the three parameters to the solution of the linear equation. That’s a pretty awesome demo.

Written by Paul Betts

June 18th, 2007 at 9:58 am

Posted in Microsoft, Mono / .NET

Silverlight + Ruby for .NET? Awesome.

2 comments

As part of the big hullabaloo around Mix ‘07, Microsoft announced their new Silverlight product, which is basically a less cracked-out Flash, which lets you use .NET languages (including IronPython) to create Flash-like animations and games. Finally, people can design awesome UIs and use a programming language that isn’t evil.

But more importantly, MS created a compiler for Ruby that compiles to MSIL called IronRuby. This means I can use Ruby at work and actually have other people use it. It also means that I might even learn this Silverlight thing if I can create awesome UIs in Ruby, and have it be cross-platform (even though “cross-platform” apparently doesn’t include Linux, don’t worry; Miguel’s gonna have that shit covered post-haste).

Written by Paul Betts

May 2nd, 2007 at 10:05 am

Posted in Microsoft, Mono / .NET, Ruby

I’m officially a GNOME developer…kind of

…or at least I have Subversion access for my language work in Beagle. I’ve been working on this for awhile now and the patches got so big that it was much easier to move it to a branch than try to maintain them all. You can check out my code at:

svn co http://svn.gnome.org/svn/beagle/branches/beagle-textcat-branch

What does this freaking do, you may ask? Well, the fundamental idea is that you can do a much better job at searching if you can split words up into the main piece, called the “stem”. For example “singing” => “sing”. As you can imagine, this is very language specific and tricky, so you need a way to figure out what language a piece of text is in before you can attempt to stem it. Fortunately, you can use a trick and do some statistical analysis (here’s the paper on it) to usually figure out the language, if you’ve got enough text.

As for the actual algorithm to stem the text, enter Snowball, a string processing language that’s built for writing stemmer programs. I ported the compiler generator to C# (wasn’t too hard, it had a generator for Java) so now the code is generated on-the-fly for a whole bunch of different languages from the Snowball source.

Now there’s only a few things left to do:

  • Load the stemmer classes at runtime using Reflection
  • Decide which one to use based on the language, and the biggest one…
  • Make sure that it doesn’t drive performance through the floor

Unfortunately, doing all this language analysis isn’t cheap, both in terms of memory and processor utilization. One of the things I have to do is go through the code with a fine-toothed comb trying to make it run really fast so Beagle doesn’t get bogged down

Written by Paul Betts

February 1st, 2007 at 12:02 am

Posted in Linux, Mono / .NET

Mono now ships with IronPython + extras and IKVM

I didn’t know they did this, but Mono, the Free .Net implementation now ships with IronPython Community Edition as well as FePy, a library to make .Net and Python get along a bit better. It also now ships by default with IKVM, which is a library that allows you to use Java and .Net together seamlessy (call Java objects from .Net and vice-versa).

So to review, using .Net and Mono, you can now write programs that interoperate seamlessly together in:

  • C#
  • C/C++ (.Net only)
  • Java
  • ECMAScript (aka Javascript)
  • Visual Basic
  • Python
  • Boo
  • MSIL

That’s pretty awesome; hopefully soon this will catch on and we’ll end the “Man, I want to use this library but it’s written in…” problem once and for all.

Written by Paul Betts

January 25th, 2007 at 6:13 pm

Why Ruby is so much shorter

Chuck:
What features or aspects of Ruby enable it to be half the number of lines as Boo?

Well, there are several aspects of Ruby that allow it to be smaller. Firstly, I’m a better functional coder than I was when I wrote the Boo version, so some of it is certainly because of that. However, several aspects of Ruby make the code much more elegant than it was; I’ll highlight a few in this blog entry.

Using yield effectively

If you judiciously use yield to retrieve extra information from the caller, you can make your code read much better. For example, here’s an excerpt from the main() of my program

# Process the library
library.load file_list do |progress|
    puts _("%s%% complete") % (progress * 100.0)
end

library.find_soundtracks do |curname|
    print _("’%s’ may be a soundtrack or compilation. Is it? (Y/n) ") % curname
    (STDIN.gets =~ /^[Nn]/ ? false : true)
end

list = library.create_action_list(results[:target],
                  results[:musicformat],
                  results[:sndtrkformat]) do |tag, invalid|
    puts _("The tag ‘%s’ has invalid characters; ‘%s’ are not allowed") % [tag, invalid]
    puts _("Please enter a replacement:")
    STDIN.gets
end

# …. snip -> in find_soundtracks …

# Call out the handler
@is_soundtrack[curname] = true if yield(curname)

See how clean the main function reads? This kind of thing is really easy and clean in Ruby; in Boo I can do the same thing using delegates but there’s more syntactic nonsense (and even more in C#).

Regular Expressions are built into everything

Regular expression support exists in Boo and it’s better than C#, but Ruby really emphasizes using them in the standard library, whereas in .NET it feels kind of like an add-on. For example, here’s a (inefficient) method to pull all the XML’ish tags from a string (like <artist>/<album> => [”artist”, “album”…)

First_Tag = /(< \S*?>)+[^< ]*/
def get_tags(xml_string)
    # Find the tags used in the string
    s = xml_string.downcase
    tags_used = []
    while First_Tag.match s do
        tags_used << $1
        s.sub! First_Tag, ”
    end
        tags_used

I’m sure as soon as I post this, someone will chime up with a “That’s a horrible way to do that!”, but my point is, Regular Expressions being built-in to a lot of methods as well as all of the match parts (\1, \2, \3…) being set to global variables like Perl makes life much easier

Dynamic class loading ain’t no thang

In Ruby, it’s even easier than C# or Boo to load new classes, because the “using” statement (”require”) isn’t some special declaration, it’s a statement just like any other. This sample loads all the classes that can dig information out of music files:


def load_taggers(*paths)
    # Load the defaults, then the ones specified in the param
    paths.each do |x|
        Pathname.new(x).each_entry { |y| require File.join(x,y) if y.extname == '.rb' }
    end

    # Now reflect through the objects and find ones that match
    @taggers = []
    tagger_classes = ObjectSpace.each_object(Class) do |x|
        pm = x.public_instance_methods(true)
        next unless pm.include? 'get_tags?' and pm.include? 'song_info'
        @taggers < < x.instance
    end
    @taggers = nil unless @taggers.size > 0
end

Basically in this sample, we load all files in a list of directories, then we dig through all the classes looking for ones that implement the get_tags? and song_info methods. If so, we add the singleton instance to an array (All tag-retrieving classes are Singletons).

Right now, I only have a dummy implementation and one that uses TagLib, but I intend to add a few more to pick up WMA/M4A's, and so all I have to do to implement that is add two more files in those directories.

Written by Paul Betts

January 17th, 2007 at 1:09 pm

Posted in Mono / .NET, Ruby