在C#中动态更改if语句的条件

时间:2012-09-05 09:23:29

标签: c# conditional-statements

我正在研究一种算法,其目的是创建一个特定事件发生的日期集合(这样我可以在MonthCalendar控件上加粗它们,或以其他方式显示它们)。

现在,对于可以使用常规函数描述的简单时间间隔(例如,如果事件发生在每周一或每10天),这不是问题。

当我有一个不规则事件的事件时(如果事件发生在每个星期五,如果该月的第一天是星期二和那种事件),就会出现真正的问题。

由于我无法预测该条件的格式,甚至无法预测需要满足的条件数量,因此我需要找到一种方法来了解如何在运行期间更改相应if语句中的条件 - 时间。

事件的定义存储在SQL数据库中。现在我的想法是使用List,其中每个元素都是一个条件,然后将它们传递给适当的if语句(如果有多个语句)或将它们连接成一个字符串并传递给相应的if语句。

这种方法是否可行,我该怎么做,或者我需要找另一种方法,在这种情况下请给我一个建议。

由于

4 个答案:

答案 0 :(得分:3)

您可以使用通用委托Predicate<T>。 (请参阅MSDN上的Predicate(T) Delegate

Predicate<IConditionParameters>将返回布尔值,IConditionParemeters抽象出一组条件参数,委托自身封装了一个返回值计算的逻辑。

public class SimpleConditionParameters : IConditionParameters
{
   public int XValue { get; set; }
}

public class ComplexConditionParameters : IConditionParameters
{
   public int XValue { get; set; }

   public int YValue { get; set; }

   public bool SomeFlag { get; set; }
}

var conditions = new List<Predicate<IConditionParameters>>();
Predicate<SimpleConditionParameters> simpleCondition = (p) => 
{
   return p.XValue > 0;
};

Predicate<ComplexConditionParameters> complexCondition = (p) => 
{
   return p.SomeFlag && p.XValue > 0 && p.YValue < 0;
};

conditions.Add(simpleCondition);
conditions.Add(complexCondition);

答案 1 :(得分:2)

另一种可能性是使用CodeDom在运行时动态生成代码,如下所示:

public class DynamicIfStatementEvaluator
{
    public bool EvaluateBools()
    {
        // Create a new instance of the C# compiler
        //from http://mattephraim.com/blog/2009/01/02/treating-c-like-a-scripting-language/

        CSharpCodeProvider compiler = new CSharpCodeProvider();

        // Create some parameters for the compiler
        CompilerParameters parms = new CompilerParameters
        {
            GenerateExecutable = false,
            GenerateInMemory = true
        };
        parms.ReferencedAssemblies.Add("System.dll");


        // Try to compile the string into an assembly
        CompilerResults results = compiler.CompileAssemblyFromSource(parms, new string[]
                                {@"using System;

                                    class BoolEvaluator
                                    {
                                        public bool EvalBoolean()
                                        {
                                            return " + InsertBooleanStringHere! + @";
                                        }               
                                    }"});

        if (results.Errors.Count == 0)
        {
            object myClass = results.CompiledAssembly.CreateInstance("BoolEvaluator");
            if (myClass != null)
            {
                object boolReturn = myClass.GetType().
                                         GetMethod("EvalBoolean").
                                         Invoke(myClass, null);
                return Convert.ToBoolean(boolReturn);
            }
        }
        else
        {
            foreach (object error in results.Errors)
            {
                MessageBox.Show(error.ToString());
            }
        }
        return false;
    }        
}

添加using语句以使用System.CodeDom.Compiler;

答案 2 :(得分:0)

您可能会有不同类型的事件,例如DailyEventWeeklyEventMonthlyEVent等,所有事件都实现了一个名为{{1的方法的给定接口(或类似的东西)和另一个名为CanFire

这将允许您创建各种类型的事件,每个事件都将实现它自己的逻辑,该逻辑决定是否需要触发它。

这将允许您创建列表并迭代事件,如果Execute产生true,则调用CanFire。这将允许您使每个事件类型具有自己的触发和执行逻辑。

答案 3 :(得分:0)

你可以这样做:

public abstract class Condition
{
   public abstract bool ConditionMet(params[] parameters); 
}

public class DateTimeCondition : Condition
{
    public override bool ConditionMet(params[] parameters)
    {
       // check condition against DateTime values available inside parameters
    }
}

public class MoreThen10: Condition
{
    public override bool ConditionMet(params[] parameters)
    {
       // check condition against numeric values more then 10
    }
}

... // and so on 

在你可以获得somwhere全局条件集合之后:

List<Condition> conditions = new List<Condition>() {new DateTimeCondition(), new MoreThen10Condition(),...}; 

当你要检查是否满足所有条件时,可以

conditions.All(condition=>condition.ConditionMet(..parameters of if...));

当然,这只是一个基本概念,一个草图,没有具体的实现,你可以复制/粘贴。