Functionally dynamic?

I was just playing with this tonight, but I don’t know it’s worth anything.  I thought of it after some conversations with Matt Podwysocki back at KaizenConf on how do apply some functional ideas in C#.  First, I started with a simple class:

public class OriginalProduct
{
    public decimal Price { get; set; }
    public decimal Cost { get; set; }

    public decimal CalculateProfit()
    {
        return Price - Cost;
    }
}

To do anything interesting, functional-wise, like swapping implementations or doing things like decorators is annoying or impossible.  But if I went this (albeit weird) direction:

public class Product
{
    public decimal Price { get; set; }
    public decimal Cost { get; set; }

    public Product()
    {
        CalculateProfit = calculateProfit;
    }

    public Func<decimal> CalculateProfit { get; set; }

    private decimal calculateProfit()
    {
        Console.WriteLine("Calculating profit");
        return Cost == 0 ? 0m : Price - Cost;
    }
}

Yes, weird.  But tests look rather normal, except a function is a property:

[Test]
public void No_change()
{
    var product = new Product {Price = 11, Cost = 10};

    product.CalculateProfit().ShouldEqual(1m);
}

Because you can invoke delegate instances directly, it looks like I’m calling a function on the type.  I can do some interesting things with some simple decorator extensions:

public static class DelegateExtensions
{
    public static Func<T> Before<T>(this Func<T> func, Action before)
    {
        return () =>
                   {
                       before();
                       return func();
                   };
    }
    public static Func<T> After<T>(this Func<T> func, Action after)
    {
        return () =>
                   {
                       T value = func();
                       after();
                       return value;
                   };
    }
}

And now I can decorate my the functions at will:

[Test]
public void Decorator_fun()
{
    var product = new Product { Price = 11, Cost = 10 };

    product.CalculateProfit =
        product.CalculateProfit
                .Before(() => Console.WriteLine("Before"))
                .After(() => Console.Write("After"));

    product.CalculateProfit().ShouldEqual(1m);
}

This outputs:

Before
Calculating profit
After
1 passed, 0 failed, 0 skipped, took 1.05 seconds.

That’s just some simple decorator implementation.  Finally, I can swap out implementations at runtime:

[Test]
public void Straight_up_replacement()
{
    var product = new Product { Price = 11, Cost = 10 };

    product.CalculateProfit = () => 1500;

    product.CalculateProfit().ShouldEqual(1500m);
}

It’s still not dynamic typing, as I can’t add new members at runtime.  I have no idea if this is useful or not, as the structure is rather weird, and you’d need to do some interesting things to get polymorphism in play.  But, it might have some interesting applications in some strange scenario.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in C#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.tobinharris.com Tobin Harris

    The first thing I thought when I saw this was “stragety”. I can see me using that as simple way of implementing the strategy pattern in .NET.

    The syntax is a bit weird, so perhaps you could separate the Func<> get/set and still have a CalculateCost() method that delegates to the strategy.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    Wow – that’s pretty darn cool, Jimmy. Nice combination of features in C#.

    You should have posted this as a PTOM post for the Decorator pattern, though. :)

  • http://www.mostlyclean.com Steve Burman

    OT

    Los Techies has 58,393,000 subscribers!! Really?!?

    *stats by Feedburner

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Steve

    Ha! No way! LT doesn’t have the clout!

    I, on the other hand, do have the clout. That’s my fake feedcount. I need the daily ego boost.