1

Is it possible to build function at runtime in c#?

Say I have this method:

List<object> DoSomeWork(List<object> listOfItems, bool boolA, bool boolB)
{
   var resultsList = new List<object>();

   foreach (var value in listOfItems)
   {
      var resultOfWork = CallFunction(value);

      if (boolA)
      {
          resultOfWork = AnotherFunctionCall(resultOfWork);
      }

      if (boolB)
      {
          resultOfWork = ThirdFunctionCall(resultOfWork);
      }

      resultsList.Add(resultOfWork);
   }

   return resultsList;
}

Is there a way I can dynamically build a function at runtime to prevent the need to check boolA and boolB for every iteration of the loop?

In my head I'd have something that looks like this:

List<object> DoSomeWork(List<object> listOfItems, bool boolA, bool boolB)
{
   Func<object, object> processor = (toProcess) =>
   {
       var resultOfWork = CallFunction(toProcess);
   }

   if (boolA)
   {
       processor += { resultOfWork = AnotherFunctionCall(resultOfWork); };
   }

   if (boolB)
   {
       processor += { resultOfWork = ThirdFunctionCall(resultOfWork); };
   }

   processor += { return resultOfWork; };

   var resultsList = new List<object>();

   foreach (var value in listOfItems)
   {
      resultsList.Add(processor(value));
   }

   return resultsList;
}

Thanks in advance.

2 Answers 2

1

There are several ways of achieving what you wish to achieve. You can use Linq.Expression to construct a function at run-time. However, since you've got only two Boolean flags, you can take a simpler approach that uses four "pre-built" function objects, like this:

Func<object,object> processor;
if (boolA && boolB) {
    processor = v => ThirdFunctionCall(AnotherFunctionCall(CallFunction(x)));
} else if (boolA && !boolB) {
    processor = v => AnotherFunctionCall(CallFunction(x));
} else if (!boolA && boolB) {
    processor = v => ThirdFunctionCall(CallFunction(x));
} else {
    processor = v => CallFunction(v);
}
var resultsList = listOfItems.Select(processor).ToList();

The bulk of the logic is in the chain of if conditionals, which enumerate all four possibilities for the pair {boolA, boolB}, and assigns the processor functor a lambda expression with the appropriate functionality.

Please note the absence of the explicit foreach loop, which can be replaced now with a LINQ call of Select(...) followed by ToList().

Sign up to request clarification or add additional context in comments.

2 Comments

Sure, I had considered this approach but what's putting me off is that in my real problem CallFunction, AnotherFunctionCall and ThirdFunctionCall are all semi-complex chunks of inline logic. I suppose I could always pull them out into separate functions. I'm interested in what you've said about Linq.Expression, how could I this to solve my problem? Thanks for your suggestion.
@psand2286 Take a look at this answer that illustrates the concept.
0

(Updated) This example builds and compiles a function that varies based on the results you passed in.

    public static object CallFunction(object item) { return item; }
    public static object AnotherFunctionCall(object item) { return item; }
    public static object ThirdFunctionCall(object item) { return item; }

    public static MethodInfo CallFunctionMethodInfo = typeof(BuildFunction).GetMethod("CallFunction");
    public static MethodInfo AnotherFunctionCallMethodInfo = typeof(BuildFunction).GetMethod("AnotherFunctionCall");
    public static MethodInfo ThirdFunctionCallMethodInfo = typeof(BuildFunction).GetMethod("ThirdFunctionCall");

    public static Func<object, object> CreateFunc(bool boolA, bool boolB)
    {
        var objectParameter = Expression.Parameter(typeof(object));
        var returnVar = Expression.Variable(typeof(object), "returnVar");

        var commands = new List<Expression>();

        commands.Add(
            Expression.Assign(
            returnVar,
            Expression.Call(CallFunctionMethodInfo, objectParameter)));

        if (boolA)
        {
            commands.Add(
                Expression.Assign(
                returnVar,
                Expression.Call(AnotherFunctionCallMethodInfo, returnVar)));
        }

        if (boolB)
        {
            commands.Add(
                Expression.Assign(
                returnVar,
                Expression.Call(ThirdFunctionCallMethodInfo, returnVar)));
        }

        commands.Add(returnVar);

        var body = Expression.Block(new[] { returnVar }, commands);

        return Expression.Lambda<Func<object, object>>(body, objectParameter).Compile();
    }

Call this function from your code Func<object, object> processor = CreateFunc(boolA,boolB);

2 Comments

The resultant expression tree is incorrect, because you keep passing the original parameter to all three functions.
OK. I believe the updated code should work properly now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.