private override

4Jun/103

Teaching StructureMap About C# 4.0 Optional Parameters and Default Values

This week I ran into wanting to use C# 4.0 optional parameters, but wanted StructureMap (my IoC tool of choice) to respect the default value specified for those optional parameters.

The Problem

In this example, we’ll be pulling a command out of the container.  The important part is the optional constructor parameter (level), and it’s default value (Level.Info).

public class LogCommand

{

    IDestination _destination;

    Level _level;

 

    public LogCommand(

        IDestination destination, Level level = Level.Info)

    {

        _destination = destination;

        _level = level;

    }

 

    /* logging code here */

}

 

Here is your basic usage, but doesn’t work since StructureMap doesn’t know how to take advantage of the optional parameters with default values.

var container = new Container(config =>

{

    config.Scan(scanner =>

    {

        scanner.TheCallingAssembly();

        scanner.AddAllTypesOf<IDestination>();

        scanner.WithDefaultConventions();

    });

});

 

var logCommand = container.GetInstance<LogCommand>();

 

The last line results in an exception because StructureMap doesn’t know how to fill in the level parameter.

The Solution

We can solve this by adding a new convention.  One that adds information about default constructor arguments.  Here is the implementation of the convention:

public class DefaultCtorParameterConvention : IRegistrationConvention

{

    public void Process(Type type, Registry registry)

    {

        if(type.IsAbstract || type.IsEnum)

            return;

 

        var ctor = type.GetGreediestCtor();

 

        if(!ctor.HasOptionalParameters())

            return;

 

        var inst = registry.For(type).Use(type);

 

        foreach(var param in ctor.GetOptionalParameters())

            inst.Child(param.Name).Is(param.DefaultValue);

    }

}

Note: GetGreediestCtor, HasOptionalParameters, and GetOptionalParameters are extension methods.  We’ll see their implementation shortly.

The convention inherits from the IRegistrationConvention, which is how you implement new conventions in StructureMap.  It has only one method: Process.  We filter out types that are abstract, are enums, or have constructors that don’t have optional parameters.  Once we realize we have a constructor we want to deal with, we use the Child method, that sets either a property or a constructor argument (for our case, it’ll always be a constructor argument), and then we set it’s value to the parameter’s default value, as provided by the ParameterInfo object, for each optional parameter.

Minor Details

Curious about the implementation of GetGreediestCtor or the *OptionalParameters methods?  If not, skip this section.

public static bool HasOptionalParameters(

    this ConstructorInfo ctor)

{

    return ctor.GetOptionalParameters().Any();

}

 

public static IEnumerable<ParameterInfo> GetOptionalParameters(this ConstructorInfo ctor)

{

    return ctor.GetParameters().Where(

        param => param.Attributes

            .HasFlag(ParameterAttributes.Optional));

}

 

public static ConstructorInfo GetGreediestCtor(

    this Type target)

{

    return target.GetConstructors()

        .WithMax(ctor => ctor.GetParameters().Length);

}

 

public static T WithMax<T>(

    this IEnumerable<T> target, Func<T, int> selector)

{

    int max = -1;

    T currentMax = default(T);

 

    foreach(var item in target)

    {

        var current = selector(item);

        if(current <= max)

            continue;

 

        max = current;

        currentMax = item;

    }

 

    return currentMax;

}

 

 

The Usage

Here’s how to use your new convention.

var container = new Container(config =>

{

   config.Scan(scanner =>

   {

       scanner.TheCallingAssembly();

       scanner.AddAllTypesOf<IDestination>();

       scanner.WithDefaultConventions();

       scanner.Convention<DefaultCtorParameterConvention>();

   });

});

 

var logCommand = container.GetInstance<LogCommand>();

 

Now, when we pull the LogCommand out of the container, the level parameter gets defaulted to Level.Info, just like we specified in the constructor.  Sweet!

Conclusion

This implementation is somewhat limiting, but the version I have in my github repo is a little more open and configurable.  It allows you to customize the instance key/name you use when registering your type, and also allows you to do additional, non-standard registrations if you need to.

Also, this doesn’t work if you’ve selected a constructor using the SelectConstructor config API from StructureMap, I’m not sure how to tap into that facility to look for that constructor rather than the greediest.

Am I missing something?  Did something not make sense?  Leave me a note!

11Dec/091

Single File Split Buffers in Visual Studio!

Man, I’d searched for this feature time and time again.  And finally found it here: http://www.kevinwilliampang.com/post/Visual-Studio-Split-Views.aspx

If you don’t want to follow the link…

Just double click that guy, or drag it downward, and you’ve split your file into two buffers.  Awesomeness.

split

18Nov/090

Don’t Single Me out!

In my few days of being a developer, I’ve heard and seen lots of talk about Singletons.  Things like

Singletons are teh suck.  Don’t use them.  EVAR.

to

Singleton’s saved my life and marriage!

In fact, I might’ve been the person that said both of these… gasp!

I never like to speak in absolutes, so I’ll say it this way (see what I did there?)… if you’re striving to implement a singleton, you’re probably wrong.  For all you guys that are right, I guess you’re right, and you can leave now, I guess.  This might help you out.

I was reading a blog from Mr. Dependency where he was talking about statics and basically what amounts to global state, and how thatultimate-geeks-multi-tool-hammer binds you into globally available, global data, which usually (always?) turns into anarchy.

How do we always get ourselves into this mess if we know it’s bad in the first place?  Well, some of us (those who are now zombocomming, from above) don’t know it’s bad in the first place, and the rest of us probably do it because it’s easy to implement, and we understand it.  Long story short, we can do the singleton implementation in our sleep, so we pull out the singleton hammer, and smack the nail.  It always goes in a little sideways, but at least it goes in.

Maybe we should be using a different hammer?

What I’d like to do now, is propose to split singleton in two.  I think there are two distinct responsibilities that the current thought of ‘singleton’ introduces. It:

  • Manages Session Scoping/Lifecycle/Lifestyle (albeit, poorly, only one strategy is available)
  • Disables the ability to create more

When I talk about this out loud, I call the two approaches the singleton implementation pattern, and singleton lifecycle.

What I am a fan of, is the singleton lifecycle.  You create one of those objects, and use it throughout the application.  You don’t get messy and allow global access to it all over the place (which necessarily happens when you have global state).  You intentionally inject it to collaborators, and  intentionally don’t inject it to non-collaborators (don’t just hand this guy out willy-nilly, he’s important).

So naturally, the naysayers ask/demand:

How do you manage that there is a public constructor on this class!?  Dev’s are going to be new’ing this thing up all over the place!

I say:

False.  Use a DI tool and let it manage it for you.  Or establish a convention with your team, and enforce it through social contracts.

Both of these approaches allow your scope lifecycle turn into whatever you want at any time, in case you decide global isn’t what you really want.  It can be application session scoped, or some other scope, test scoped, or whatever you want… incredibly flexible.

If you go with the DI tool approach, instead of tying yourself to a particular scope, you can now have any scope you want, by changing a configuration parameter.  Delaying decisions until the latest responsible moment… seems like I’ve heard that one before.

23Sep/091

Autotest… in .NET

The first time I saw autotest (presented by Anthony), the idea of Continuous Testing captured me.

I live in a .NET world most of the time, and I know of no similar solution for .NET.  It’s been awhile since that first time, and I’ve tinkered here and there trying to get something comparable, but usually come up short.  That is until I found watchr.

Watchr gave me the file change detection capabilities I needed, and the extensibility to do whatever I want when a file has been detected as changed.  This made it incredibly easy to hook up some autotest goodness in my .NET world.

You'll have to have ruby installed, and gems.  Then, the very first thing you'll have to do is

gem install watchr --source=http://gemcutter.org

Here is my watchr script:

require 'autotest.rb'

watch( '^.*UnitTest.*.cs$' ) do |match|
  run_test(match.to_s)
end

This is basically just a regex that says to watch any *.cs files that also contain the string “UnitTest”, and when it finds a change in a file matching that description, call run_test with the matched file name.

So all the magic is in autotest.rb… lets check it out:

require 'rexml/document'

def build(test_project)
  `msbuild /nologo #{test_project}`
end

def mstest(test_container, test_results_file, tests_to_run)
  tests_to_run = ([""] << tests_to_run).flatten

  File.delete(test_results_file) if File.exists?(test_results_file)
  `mstest /nologo /resultsfile:#{test_results_file} /testcontainer:#{test_container} #{tests_to_run.join(" /test:")}`
  test_results = process_mstest_results(test_results_file)
  File.delete(test_results_file) if File.exists?(test_results_file)

  return test_results
end

def process_mstest_results(results_file)
  results = {}
  File.open(results_file) do |file|
    xml = REXML::Document.new(file)

    results[:num_tests] = xml.get_elements("//UnitTestResult").length
    failures = []
    xml.elements.each("//UnitTestResult[@outcome='Failed']") do |e|
      failure = {}
      failure[:message] = e.elements["Output/ErrorInfo/Message"].get_text

      stack = e.elements["Output/ErrorInfo/StackTrace"].get_text.value
      stack_match = /^.*at (.*) in(.*):line (\d+)$/.match(stack)

      failure[:stack] = stack_match[1] if stack_match
      failure[:location] = stack_match[2] if stack_match
      failure[:line] = stack_match[3] if stack_match

      failure[:stack] = stack if !stack_match

      failures << failure
    end
    results[:failures] = failures
  end

  return results
end

def show_results(results)
  puts "#{results[:num_tests]} tests run (#{results[:failures].length} failures)"
  results[:failures].each do |failure|
      puts "---------------------------------------"
      puts "Message: #{failure[:message]}"
      puts "Location: #{failure[:location]}"
      puts "Line: #{failure[:line]}"
      puts "Stack Trace: #{failure[:stack]}"
  end
end

def run_test(file_name)
  test_container = ""
  test_results_file = "result.trx"
  test_project = ""

  system("cls")
  system("echo Detected change in:")
  system("echo   #{file_name}")
  system("echo Building and Testing")

  test_namespace = ''
  test_class = ''
  test_names = []

  File.open(file_name, "r") do |f|
    f.each do |line|
      ns_match = /^namespace (.*)$/.match(line)
      test_namespace = ns_match[1] if ns_match

      class_match = /^\s*public class (.\w*).*$/.match(line)
      test_class = class_match[1] if class_match

      test_name_match = /^\s*public void (\w*).*$/.match(line)
      test_names << test_name_match[1] if test_name_match
    end
  end

  test_names = test_names.map { |n| "#{test_namespace}.#{test_class}.#{n}" }

  build(test_project)
  results = mstest(test_container, test_results_file, test_names)
  show_results(results)
end

The key parts (I think) are the fact that I’m using MSTest to run my tests (this can easily be modified to run your framework of choice… note MSTest is not my choice ;) ).  The result parsing is also specific to the MSTest output format, but should be simple enough for any framework that can output XML. Also, I'm making some assumptions based on my project... we've got one unit test project, so I know I can run tests in a single DLL, and rebuilding only that project, I don't have to worry about choosing the correct project and output dll to build and run tests in.

To get the thing up and running, just run

watchr <path to watchr script>

Please, use/adapt/give feedback/whatever at will.

Go forth and autotest, .NET comrades!

30Mar/090

2 amazazing productivity tools

I'm in the middle of writing a bunch of XML API documentation for a prototype I just built.  I'm not really a fan of xml doc-comments, which is why I didn't do it in the first place, but the client wants API documentation, so this is definitely the best way to get it.  The two aforementioned tools?

GhostDoc

GhostDoc basically infers the documentation from the name of the method and its parameter signature.  Absolutely brilliant.  Hook this baby up with a keyboard shortcut, and blam!, it just spits out documentation with a keystroke (which of course is easy to tweak once it's there).  One of the  awesome features is that for implemented methods of an interface, it'll use the exact documentation from the doc-comments from the interface file.  Sweet.

Docu

Docu is sort of like the NDoc of old.  I know that SandCastle exists, but this is so much simpler.  It uses the Spark view engine/templating system, so that means the output is completely customizable.  Right now it comes with a single template, that is heavily inspired by rdoc rather than something like MSDN style (though I'm certain an MSDN style template will be contributed to the project soon).  The project is really young, but it is used already by FluentNHibernate (and was the reason for its inception, really).  Here is the output for the FluentNH project: FluentNH API Docs.

Amazazing.