Lambda Functions for Design By Contract

This is sadly not one of those blog posts where I show you what I have managed to achieve. Instead it’s one where I ask you if you have a solution for what I am after.

When I was at university, my professor convinced me that the benefits of design by contract were worth the cost of the implementation. In every language that I have worked with ever since, I have implemented some sort of veneer over the top of the language to enable design by contract. I’ve used all sorts of code generators or AOP systems to do it for me. As you may have seen from my last post, I’ve been on the WCF Masterclass with Juval Lowy, and I’ve been inspired by the pretty extensibility model of WCF to give DBC in C# another stab.

WCF provides class construction behavior that is nicely extensible through the use of attributes. If an attribute, for example, derives from IServiceBehaviour, then WCF will  run a method on the attribute, passing in the object that the attribute was attached to. This gives the attribute (or a helper class that it uses) the opportunity to modify some of the settings for the context of the service. This is a perfect model for me to do the same thing using predicates in a DBC system. First I just need to designate an interface class that marks a derived attribute as worth paying attention to by my class factory. Lets call it IExtensibilityBehaviour. If the class factory spots an attribute on a type it’s trying to dispense, it can provide special behavior for the class such as wrapping it, or running something like PostSharp over it to insert some code to run pre and post condition predicates. here’s an example attribute that I want to attach to a class:

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
sealed class InvariantPredicateAttribute : Attribute, IExtensibilityBehaviour
{
    Func<object, bool> Predicate { get; set; }
    public InvariantPredicateAttribute(DbcPredicate predicate)
    {
Predicate = predicate; }
    public void Validate(object x)
    {
        if (!Predicate(x)) 
            throw new ApplicationException("Invariant Predicate Failed");
    }
}

The attribute above takes a delegate as a constructor parameter and stores it in the Predicate property. I can then add the attribute to a class like so:

[InvariantPredicate((TestClass x)=>x.FirstName != null)]
public class TestClass
{
    public string FirstName { get; set; }
}

As you can see, I insert a Lambda function as the parameter, which I could then elsewhere invoke like so:

TestClass t = new TestClass()
// Do something with it
foreach (InvariantPredicateAttribute ipa in 
    typeof(TestClass).GetCustomAttributes(
        typeof(InvariantPredicateAttribute), true))
{
     ipa.Validate(t);
}

Sadly, this is where I come to a crashing halt. You can’t do this in C# 3 or less. I get the following:

C:\…\AttributeEx.cs(34,29): error CS1706: Expression cannot contain anonymous methods or lambda expressions

If you read the commentary here, from a year or two ago, it seems to imply that the problem would be solved in future builds of VS.NET. Well, I’m running the latest beta of VS.NET 2008, and it still is a problem. Which is where YOU come in. Can you think of a way for me to get round this? I’ve tried a few ideas, and I just can’t get it to work for one reason or another.

Help. Please.

About these ads

6 comments

  1. I would maybe try, instead of the attribute, putting something in the static initializer.

    In situations where I have had the need for some kind of runtime metadata-ish needs and Attributes are not an option (you can’t have a generic attribute either – MyFancyAttribute).

  2. How’s this different from passing a script as the value of an attribute, retrieving the script at runtime and executing it? I mean apart from all the syntactic sugar.

  3. I did it in a delegate that’s declared outside of the class/type. I have some prototype code somewhere that, last I checked, I *believed* worked. Not difficult, since… it was passing it around as a type… (I know, cheap hack, lambda was my original desire/intent, it just looks cool not to mention your functionality is right there although, not ver reusable but… it probably shouldnt be).

    I dont think my implementation/use case would be considered DBC it’s more of a way to do custom execution between the same properties of two implementations of an interface (maybe that’s DBC?). This allows everything to be done via generics in the differant vertical/horizontal components and then these guys (the attached delegates) + regular copy operations are cached to be executed at runtime… i’m not sure if this is a good or bad idea overall but, the net effect is that transitioning a 1000 property object becomes one line of code with some parameters to specifiy the operation (copy, create, etc) type.

    IDK, people seem to not like that fact that now things are executing that they cant see. I think it will work but, any input/cause for concern on such a design would be more than welcomed!

    -Brian Abbott

  4. Hi Brian,

    I’d be very keen to see a sample of you code. Storing the lambdas elsewhere wouldn’t help with the DBC issue, that I blogged about elsewhere, of not being able to reference private properties and fields. But still, I’d like to see how you did it.

    Andrew

Comments are closed.