我正在研究一种算法,其目的是创建一个特定事件发生的日期集合(这样我可以在MonthCalendar控件上加粗它们,或以其他方式显示它们)。
现在,对于可以使用常规函数描述的简单时间间隔(例如,如果事件发生在每周一或每10天),这不是问题。
当我有一个不规则事件的事件时(如果事件发生在每个星期五,如果该月的第一天是星期二和那种事件),就会出现真正的问题。
由于我无法预测该条件的格式,甚至无法预测需要满足的条件数量,因此我需要找到一种方法来了解如何在运行期间更改相应if语句中的条件 - 时间。
事件的定义存储在SQL数据库中。现在我的想法是使用List,其中每个元素都是一个条件,然后将它们传递给适当的if语句(如果有多个语句)或将它们连接成一个字符串并传递给相应的if语句。
这种方法是否可行,我该怎么做,或者我需要找另一种方法,在这种情况下请给我一个建议。
由于
答案 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)
您可能会有不同类型的事件,例如DailyEvent
,WeeklyEvent
,MonthlyEVent
等,所有事件都实现了一个名为{{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...));
当然,这只是一个基本概念,一个草图,没有具体的实现,你可以复制/粘贴。