C# - Getting rid of casting-parenthesis

Normally casting should be avoided if possible and when casting is necessary, use the as-operater and check the result for null! But sometimes a plain cast seems to be valid and necessary and when this is the case, I absolutely hate to type the parenthesis. So my new little friend is this extension method:

public static class CastExtension
{
    public static T Cast<T>(this object obj)
    {
        return (T) obj;
    }
}

instead of:

((IBar) foo).DoSomething();

you can now trade two parenthesis for two angle brackets:

foo.Cast<IBar>().DoSomething().

Doesn't seem to be much of a difference, but it types much nicer!

Published on 01/02/2010 at 12:01 by , tags ,

Evaluating build tools for altdotmono.org - part two

Three days ago I thought about which build tool to use for the altdotmono.org projects. I came up with the conclusion, that CMake, SCons and Autotools should be on my short list.

First a small correction: I wrote, that Rant doesn't have any native CSharp support. That's not true! It has a CSharp generator, that can be used as simple as this:

import 'csharp'
gen CSharp, "example.dll", :sources => sys["**/*.cs"]

Unfortunately it doesn't work very well. Simply adding a reference makes it fail:

gen CSharp, "example.dll", :sources => sys["**/*.cs"],
                           :libs    => ["System.Web"]

rant: [ERROR] in file `/usr/lib/ruby/1.8/rant/rantlib.rb', line 577: 
              in prerequisites: no such file or task: `System.Web'

This should be easy to fix in Rant, I just added a bug report. Sadly Rant doesn't seem to be very popular. There has been no commit within a year, only ten bug reports within 3 years and although Rant is packaged in Debian, not a single package in Lenny uses Rant as a build tool. (But I should also add, that not more than six packages build-depend on Rake compared to more than 100 packages depending on CMake and more then 50 packages depending on SCons.)

Rake is much more popular but misses some features, that Rant provides (e.g. MD5 checksums instead of timestamps for dependency checking). I haven't really considered Rake yet, because I couldn't find any project using it for building C#/Mono projects. But after playing around with SCons and CMake I didn't had the feeling of having found the right tool, so I tried Rake anyway.

I wrote a custom TaskLib supporting gmcs within half an hour, so that my Rakefile for building two libs now looks like this:

require 'rake'
require 'rake/gmcs'

task :default => ['StructureMap.dll', 'StructureMap.AutoMocking.dll']

signingKey = 'structuremap.snk'


#
# The Core StructureMap Assembly
#
sources    = FileList['StructureMap/**/*.cs']
references = ['System.Web', 'System.Configuration']

Rake::GmcsTask.new 'StructureMap.dll' => {:sources => sources,
  :references => references, :keyfile => signingKey}


#
# StructureMap Rhino.Mocks automocking support
#
sources    = FileList['StructureMap.AutoMocking/**/*.cs']
references = ['#../../Rhino.Mocks.dll', '#StructureMap.dll']

Rake::GmcsTask.new 'StructureMap.AutoMocking.dll' => {:sources => sources,
  :references => references, :keyfile => signingKey}

This comes pretty close to what I would like to have. The Gmcs task basically reads:

"Build StructureMap from the list of sources, linking to the list of references and sign it with the signingKey."

GmcsTask will create a Rake file task and will automatically make it pre-depend on the sources, the local references and the key file. This means, that StructureMape.Automocking.dll will only be built. if the timestamp of the sources, of StructureMap.dll, RhinoMocks.dll or the key file change. Because I can't make a dependency to a reference called "System.Web", I needed a way to specify which references are local file dependencies and which are not. This is simply done by prefixing the reference with '#', something I saw in the SCons build files of Diva.

I think this is pretty easy and it can probably be made even easier by writing a Visual Studio *.csproj-Parser, which extracts the sources, references and resources from the project files. And by even adding a solution parser, the whole build of multiple projects might be stripped down to something like:

task :default => SolutionParser.new('StructureMap.sln').ProjectTasks

"Easy Peasy" as Jamie Oliver would say. I'm not sure if it is a good idea to completely rely on the Visual Studio solution and project files, but I think I will try to drive the Rake approach for building the Alltdotmono projects a little bit further.

Published on 27/09/2008 at 12:35 by , tags , , , ,

Unit test of the day

5 unit tests covering a single line of code:

[TestFixture]
public class A_SwissRounding
{
    private SwissRounding _rounding = new SwissRounding();

    [Test]
    public void Should_round_down_to_zero_when_having_zero_to_two_and_a_half()
    {
        Assert.AreEqual(1.00m, _rounding.Round(1.0010m));
        Assert.AreEqual(1.00m, _rounding.Round(1.0249m));
    }

    [Test]
    public void Should_round_up_to_five_when_having_two_and_a_half_to_five()
    {
        Assert.AreEqual(1.05m, _rounding.Round(1.0250m));
        Assert.AreEqual(1.05m, _rounding.Round(1.0490m));

    }
    [Test]
    public void Should_round_down_to_5_when_having_five_to_seven_and_a_half()
    {
        Assert.AreEqual(1.05m, _rounding.Round(1.0510m));
        Assert.AreEqual(1.05m, _rounding.Round(1.0749m));
    }

    [Test]
    public void Should_round_up_to_10_when_having_seven_and_a_half_to_ten()
    {
        Assert.AreEqual(1.10m, _rounding.Round(1.0760m));
        Assert.AreEqual(1.10m, _rounding.Round(1.0990m));
    }

    [Test]
    public void Should_not_round_multiples_of_five()
    {
        Assert.AreEqual(1.00m, _rounding.Round(1.0000m));
        Assert.AreEqual(1.05m, _rounding.Round(1.0500m));
        Assert.AreEqual(1.10m, _rounding.Round(1.1000m));
    }
}

public class SwissRounding
{
    public decimal Round(decimal value)
    {
        return Math.Round(value*20, MidpointRounding.AwayFromZero)/20;
    }
}

:-)

Published on 26/08/2008 at 18:16 by , tags , ,

Powered by Publify | Photo Startup stock photos