098e5c1a565b47e9860539fbebc3fa98

There is a page in a C# web site that has a requirement to do something like the below. To me this is basically the same problem as a command line application that takes multiple parameters that must override each other. This is ugly to me, and I'm looking for an established pattern that solves this problem. After poking around http://martinfowler.com/eaaCatalog/ I didn't see anything that immediately jumped out at me as the solution.

String foo = Request.QueryString["foo"];
if (!String.IsNullOrEmpty(foo))
{
  DoFooWork(foo);
}
else
{
  String bar = Request.QueryString["bar"];
  if (!String.IsNullOrEmpty(bar))
  {
    DoBarWork(bar);
  }
  else
  {
    String baz = Request.QueryString["baz"];
    if (!String.IsNullOrEmpty(baz))
    {
      DoBazWork(baz);
    }
    else
    {
      String beer = Request.QueryString["beer"];
      if (!String.IsNullOrEmpty(beer))
      {
        DoBeerWork(beer);
// ...

Refactorings

No refactoring yet !

098e5c1a565b47e9860539fbebc3fa98

slf

March 24, 2009, March 24, 2009 14:49, permalink

No rating. Login to rate!

Maybe a psuedo-registry pattern? Also, it's probably worth mentioning this is .NET 3.5 so any Linq / Lambda / Functional programming answers are valid too.

Fa1a0dd6b85652d6cee91f1d548a1e88

AG

March 24, 2009, March 24, 2009 15:55, permalink

No rating. Login to rate!

Need more context. What is the intent of this code? You could probably roll this into a map using the querystring value as a key into it...
(Keep in mind that the PoEAA book is intended for higher "Enterprise" patterns.)

D41d8cd98f00b204e9800998ecf8427e

uvw

March 24, 2009, March 24, 2009 17:13, permalink

No rating. Login to rate!

May be something like this.

internal interface IQueryStringProcessor : IEnumerable<KeyValuePair<string, Action<string>>>
{
    void Add(string key, Action<string> action);
    void Process(IDictionary<string, string> queryString);
    Action Fallback { get; set; }
};

internal class FooBarBazQueryStringProcessor : IQueryStringProcessor
{
    private readonly List<KeyValuePair<string, Action<string>>> plan;

    public FooBarBazQueryStringProcessor(Action fallback)
    {
        plan = new List<KeyValuePair<string, Action<string>>>();
        Fallback = fallback;
    }

    public void Add(string key, Action<string> action)
    {
        plan.Add(new KeyValuePair<string, Action<string>>(key, action));
    }

    public void Process(IDictionary<string, string> queryString)
    {
        foreach (var pair in plan) {
            string value;

            if (!queryString.TryGetValue(pair.Key, out value) ||
                string.IsNullOrEmpty(value)) {
                continue;
            }
            
            pair.Value(value);
            return;
        }

        if (Fallback != null) {
            Fallback();
        }
    }

    public Action Fallback { get; set; }

    public IEnumerator<KeyValuePair<string, Action<string>>> GetEnumerator()
    {
        return plan.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    /// <summary>
    /// Sample usage
    /// </summary>
    public static void Main()
    {
        Action fallback = () => {
            throw new ArgumentException("The query string does not contain any known parameters.");
        };

        var processor = new FooBarBazQueryStringProcessor(fallback) {
                {"foo", foo => DoFooWork(foo) },
                {"bar", bar => DoBarWork(bar)},
                {"baz", baz => DoBazWork(baz)}
        };
        
        // ...

        var request = new Dictionary<string, string> {
                {"foo", "some foo data"}
        };
        
        // ...


        processor.Process(request);
    }
}
098e5c1a565b47e9860539fbebc3fa98

slf

March 24, 2009, March 24, 2009 18:43, permalink

No rating. Login to rate!

@uvw, I like it. Kind of reminds me of Perl.

@AG comments made me remember to pull out the GoF book. I think this is the solution:
http://www.dofactory.com/patterns/PatternStrategy.aspx

What do you guys think?

72f36daa501cf8f5bb861210edd9232d

Moonshield

March 27, 2009, March 27, 2009 01:39, permalink

1 rating. Login to rate!

I've already posted something similar, you can take a look at http://refactormycode.com/codes/493-twitter-esque-relative-dates
The code below is probably what I would do, it is very similar to the code above but without the overhead

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication4
{
    class Program
    {
        private static Dictionary<string, Action<string>> _QueryPriority;

        static void Main(string[] args)
        {
            if (_QueryPriority == null)
            {
                _QueryPriority = new Dictionary<string, Action<string>>();
                _QueryPriority.Add("Foo", DoFooWork);
                _QueryPriority.Add("Bar", DoBarWork);
                _QueryPriority.Add("Beer", DoBeerWork);
                _QueryPriority.Add("Coffee", DoCoffeeWork);
            }

            var action = Program._QueryPriority.FirstOrDefault(x => !string.IsNullOrEmpty(Request.QueryString[x]));         
            if (action.Key != null)
                action.Value.Invoke(action.Key);
        }

        private static void DoFooWork(string pParam) { Console.WriteLine(pParam); }
        private static void DoBarWork(string pParam) { Console.WriteLine(pParam); }
        private static void DoBeerWork(string pParam) { Console.WriteLine(pParam); }
        private static void DoCoffeeWork(string pParam) { Console.WriteLine(pParam); }
    }
}
098e5c1a565b47e9860539fbebc3fa98

slf

March 27, 2009, March 27, 2009 19:48, permalink

No rating. Login to rate!

Very nice, clean and concise Moonshield. I love it. Going back to the original intent, is there an established pattern for this? If not we should come up with a name. This is basically a "Action Registry" to me.

D41d8cd98f00b204e9800998ecf8427e

uvw

March 27, 2009, March 27, 2009 22:25, permalink

No rating. Login to rate!
In general this is the "Pattern Matching" [http://en.wikipedia.org/wiki/Pattern_matching] pattern (oops ;))
F20947a52edc6fe8c8929a739ee6e70d

Jean

April 3, 2009, April 03, 2009 21:01, permalink

No rating. Login to rate!

Hello. That's very nice site but I've seen this before here <a href="http://href.inguaro.com/f183d07eb9ff97f92a80d3965dce9974">http://text.inguaro.com/f183d07eb9ff97f92a80d3965dce9974</a>
f183d07eb9ff97f92a80d3965dce9974

Hello. That's very nice site but I've seen this before here <a href="http://href.inguaro.com/f183d07eb9ff97f92a80d3965dce9974">http://text.inguaro.com/f183d07eb9ff97f92a80d3965dce9974</a>
f183d07eb9ff97f92a80d3965dce9974
3018f10e3f35bff07b5b0e1a541c103a

Lewis

April 3, 2009, April 03, 2009 21:01, permalink

No rating. Login to rate!

The night of the fight, you may feel a slight sting. That's pride f*cking with you. F*ck pride. Pride only hurts, it never helps.
f183d07eb9ff97f92a80d3965dce9974

The night of the fight, you may feel a slight sting. That's pride f*cking with you. F*ck pride. Pride only hurts, it never helps.
f183d07eb9ff97f92a80d3965dce9974

Your refactoring





Format Copy from initial code

or Cancel