tags:

views:

295

answers:

1

I'm trying to use lambda syntax to be able to swap out search rule engines at runtime.

In the below example, what syntax do I need to be able to pass the name of the method to my GetSearchResults method so that the GetSearchResults method can use the appropriate logic to decide which results to return?

string searchRulesMethodName = "SearchRules1(entry)";
var results = GetSearchResults(p => searchRulesMethodName);

Here is the complete code:

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

namespace TestLambda2
{
    class Program
    {
        static void Main(string[] args)
        {
            string searchRulesMethodName = "SearchRules1(entry)";
            var results = GetSearchResults(p => searchRulesMethodName);
            foreach (string entry in results)
            {
                Console.WriteLine(entry);
            }
            Console.ReadLine();
        }

        //only returns some entries
        public static bool SearchRules1(string entry)
        {
            if (entry == "one" || entry == "two") return true;
            return false;
        }

        //returns all entries
        public static bool SearchRules2(string entry)
        {
            return true;
        }

        public static List<string> GetSearchResults(Predicate<string> p)
        {
            string[] allEntries = { "one", "two", "three", "four", "five", "six", "seven" };
            List<string> results = new List<string>();
            foreach (string entry in allEntries)
            {
                if (p.Invoke(entry))
                {
                    results.Add(entry);
                }
            }
            return results;
        }

    }
}

ANSWER:

Thanks Marc, that was exactly what I wanted to do. Using reflection also solved the "how do I tell it the property signature" problem as well:

static void Main(string[] args)
{
    string searchRulesMethodName = "SearchRules2";
    Predicate<string> predicate = (Predicate<string>) Delegate.CreateDelegate(typeof(Predicate<string>),
        typeof(Program).GetMethod(searchRulesMethodName));
    var results = GetSearchResults(predicate);

    foreach (string entry in results)
    {
        Console.WriteLine(entry);
    }
    Console.ReadLine();
}
+5  A: 

To use a string, you'd have to use reflection to get the delegate;

string searchRulesMethodName = "SearchRules1";
Predicate<string> predicate = (Predicate<string>)
    Delegate.CreateDelegate(typeof(Predicate<string>),
        typeof(Program).GetMethod(searchRulesMethodName));
var results = GetSearchResults(predicate);

Of course, a switch would be a lot faster and safer if you know all the options at compile-time!

Predicate<string> predicate;
switch (searchRulesMethodName) {
    case "SearchRules1": predicate = SearchRules1; break;
    case "SearchRules2": predicate = SearchRules2; break;
    default: throw new InvalidOperationException("Unknown filter: "
        + searchRulesMethodName);
}
var results = GetSearchResults(predicate);
Marc Gravell