【问题标题】:Can I dynamically build a function at runtime in c#?我可以在 C# 中在运行时动态构建函数吗?
【发布时间】:2014-06-26 03:49:38
【问题描述】:

c#可以在运行时构建函数吗?

说我有这个方法:

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;
}

有没有一种方法可以在运行时动态构建函数,以防止每次循环迭代都需要检查 boolA 和 boolB?

在我的脑海中,我会有这样的东西:

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;
}

提前致谢。

【问题讨论】:

    标签: c# function dynamic runtime func


    【解决方案1】:

    有几种方法可以实现您希望实现的目标。您可以使用Linq.Expression 在运行时构造函数。但是,由于您只有两个布尔标志,您可以采用更简单的方法,使用四个“预构建”函数对象,如下所示:

    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();
    

    大部分逻辑位于if 条件链中,它枚举{boolA, boolB} 对的所有四种可能性,并为processor 函子分配具有适当功能的lambda 表达式。

    请注意没有显式的foreach 循环,现在可以用Select(...) 后跟ToList() 的LINQ 调用替换它。

    【讨论】:

    • 当然,我考虑过这种方法,但让我失望的是,在我的真正问题中,CallFunctionAnotherFunctionCallThirdFunctionCall 都是半复杂的内联逻辑块。我想我总是可以将它们拉到单独的功能中。我对你所说的Linq.Expression 很感兴趣,我该如何解决我的问题?感谢您的建议。
    • @psand2286 看看说明这个概念的this answer
    【解决方案2】:

    (更新) 此示例构建并编译了一个函数,该函数会根据您传入的结果而有所不同。

        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();
        }
    

    从你的代码Func&lt;object, object&gt; processor = CreateFunc(boolA,boolB);调用这个函数

    【讨论】:

    • 生成的表达式树不正确,因为您一直将原始参数传递给所有三个函数。
    • 好的。我相信更新后的代码现在应该可以正常工作了。
    猜你喜欢
    • 2012-06-16
    • 2010-09-30
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    相关资源
    最近更新 更多