C# 使用CSharpCodeProvider允许用户创建函数
我有一个现有的asp.net(c#)应用程序。我需要为用户提供一种创建灵活规则的方法,以计算给定雇佣日期和注册日期的生效日期 可能使用的一些规则示例:C# 使用CSharpCodeProvider允许用户创建函数,c#,.net,runtime,C#,.net,Runtime,我有一个现有的asp.net(c#)应用程序。我需要为用户提供一种创建灵活规则的方法,以计算给定雇佣日期和注册日期的生效日期 可能使用的一些规则示例: 雇佣日期或注册日期中的较晚者 雇佣+90天 注册日期后的第一个月 如果报名日期在当月15日之前,则生效日期为下个月1日。如果是在15号或之后,则是该月的第1天 我开始时有一些偏移字段(日偏移、月偏移等),但当我遇到新的需求时,我逐渐意识到当前的方法不够灵活 我想做的是允许最终用户定义一个函数,该函数返回给定两个参数(hiredate、enroll
有没有办法确保该功能没有任何副作用?例如,没有I/O。没有读取或会话、缓存或应用程序 请参见我最近的回答: 本质上,您可以轻松地利用现有库来解析表达式并为这些规则发出IL。如果您看一下这些示例,就可以看到如何为用户表达式设置要利用的变量。例如,您可以定义由一些输入变量(如
HireDate
或EnrollmentDate
)和返回日期的用户表达式/谓词组成的“规则”。如果像我在链接答案中那样公开DateTime
成员,那么用户也可以利用这些成员
作为一个简单的例子,没有测试,但应该给你一个想法
您可以设置一些自定义函数以提供帮助,例如获取一个月的第一天:
public static class CustomFunctions
{
public static DateTime GetFirstDayOfMonth(DateTime date)
{
return new DateTime(date.Year, date.Month, 1);
}
}
基本的逃离设置(您必须根据需要进行自定义/调整)
ExpressionContext=newexpressioncontext();
//告诉逃跑者期待一个日期时间结果;如果表达式的计算结果不是这样,
//编译表达式时引发ExpressionCompileException
context.Options.ResultType=typeof(DateTime);
//指示Runge公开'DateTime'静态成员并
//它们可以通过“日期时间”访问。
//这与访问“DateTime.Now”的C#语法完全相同`
AddType(typeof(DateTime),“DateTime”);
AddType(typeof(CustomFunctions));
//公开关键变量,如HireDate和EnrollmentDate
变量[“HireDate”]=GetHireDate()//我想是约会时间吧
context.Variables[“EnrollmentDate”]=GetEnrollmentDate()//我想是约会时间吧
//解析表达式时,字符串自然会来自您的数据源
IGenericExpression expression=context.CompileGeneric(GetYourRule(),context);
DateTime日期=表达式.Evaluate();
那么您的规则可能如下所示:
string rule1 = "if(HireDate > EnrollmentDate, HireDate, EnrollmentDate)";
string rule2 = "HireDate.AddDays(90)";
string rule3 = "GetFirstDayOfMonth(EnrollmentDate.AddMonths(1))";
string rule4 = "GetFirstDayOfMonth(EnrollmentDate.AddMonths(if(EnrollmentDate.Day < 15, 1, 2)))";
string rule1=“如果(HireDate>EnrollmentDate,HireDate,EnrollmentDate)”;
字符串规则2=“HireDate.AddDays(90)”;
字符串规则3=“GetFirstDayOfMonth(EnrollmentDate.AddMonths(1))”;
string rule4=“GetFirstDayOfMonth(EnrollmentDate.AddMonths)(如果(EnrollmentDate.Day<15,1,2))”;
以下链接说明了您的目的。本质上,它是一种可插入的DSL,允许定义无限的日期计划和集合,然后将其传递给函数、交叉、联合等
可以使用可为空的类型吗?比方说,如果雇用日期未知,我需要能够将null传递给HireDate,而不是构建一个包含两个DateTime参数的表达式?@Aheho我想是的,但您最好避免使用它的各种隐式运算符,并使用它的
.Value
属性。例如,如果HireDate
是typeDateTime?
,而不是简单地检查if(HireDate>DateTime.Now)
您可能需要if(HireDate.Value>DateTime.Now)
。您还可以完全避免空值,使用单独的布尔标志“HasHireDate”,如果这是false
,则HireDate
可能是过去的默认值,或者只是new DateTime()
string rule1 = "if(HireDate > EnrollmentDate, HireDate, EnrollmentDate)";
string rule2 = "HireDate.AddDays(90)";
string rule3 = "GetFirstDayOfMonth(EnrollmentDate.AddMonths(1))";
string rule4 = "GetFirstDayOfMonth(EnrollmentDate.AddMonths(if(EnrollmentDate.Day < 15, 1, 2)))";