[英]Dynamically changing conditions of an if statement in C#
我正在研究一种算法,其目的是创建发生某个事件的日期集合(以便我可以在MonthCalendar控件上加粗它们,或以其他方式显示它们)。
现在,对于可以用常规功能描述的简单时间间隔(例如,如果事件在每个星期一或每10天发生一次),这不是问题。
真正的问题发生在我有不规则事件发生的事件时(例如,如果每个月的第一天是星期二,则每个星期五都发生该事件)。
由于我无法预测该条件的格式,甚至无法满足需要满足的条件数量,因此我需要找到一种在运行时如何在适当的if语句中更改条件的方法。
事件的定义存储在SQL数据库中。 现在,我的想法是使用一个List,其每个元素都是一个条件,然后将它们传递给适当的if语句(如果有多个语句),或者将它们连接到一个字符串中并传递给适当的if语句。
这种方法可行吗?我将如何做?还是需要寻找另一种方法,在这种情况下,请给我一个建议。
谢谢
您可以使用通用委托Predicate<T>
。 (请参阅MSDN上的Predicate(T)代表 )
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);
另一种可能性是使用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;
}
}
添加用于使用System.CodeDom.Compiler的using语句;
您可能拥有不同类型的事件,例如DailyEvent
, WeeklyEvent
, MonthlyEVent
等,所有这些事件都实现了给定的接口,该接口具有一个名为CanFire
(或类似名称)的方法和另一个名为Execute
。
这将允许您创建各种类型的事件,每种事件都将实现自己的逻辑,该逻辑决定是否需要触发该事件。
这将允许您创建一个列表并仅迭代事件,如果CanFire
产生true,则调用Execute
。 这将允许您使每种事件类型都有其自己的触发和执行逻辑。
好吧,你可以做这样的事情:
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
在获得全球各地条件后:
List<Condition> conditions = new List<Condition>() {new DateTimeCondition(), new MoreThen10Condition(),...};
当您要检查是否满足所有条件时,
conditions.All(condition=>condition.ConditionMet(..parameters of if...));
自然,这只是一个基本概念,一个草图,没有可以复制/粘贴的具体实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.