0

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

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

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

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

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

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

谢谢

4

4 回答 4

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);
于 2012-09-05T09:26:30.003 回答
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 添加 using 语句;

于 2013-09-17T15:34:26.007 回答
0

你可以,也许,有不同类型的事件,例如DailyEvent, WeeklyEvent,MonthlyEVent等,所有这些都实现了一个给定的接口,该接口有一个名为CanFire(或类似的东西)的方法和另一个名为Execute.

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

这将允许您创建一个列表并仅遍历事件,如果CanFire产生 true,则调用Execute. 这将允许您让每种事件类型都有自己的触发和执行逻辑。

于 2012-09-05T09:29:42.203 回答
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...));

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

于 2012-09-05T09:30:06.763 回答