使用CSharpCodeProvider允许用户创建的函数

时间:2013-02-06 13:25:52

标签: c# .net runtime

我有一个现有的asp.net(c#)应用程序。我需要为用户提供一种方法来创建灵活规则,以便根据hiredate和enrollmentdate计算生效日期。

可能使用的一些规则示例:

  1. hiredate或enrollmentdate的后期
  2. HireDate + 90 Days
  3. 报名日期后的第一个月
  4. 如果注册日期在该月的15日之前,那么生效日期是下个月的第1天。如果它在15或之后,则是在此之后的第1个月。
  5. 我开始时有一些偏移字段(日偏移,月偏移等等),但是当我遇到新的要求时,我意识到当前的方法不够灵活。

    我想要做的是允许最终用户定义一个函数,该函数返回给定两个参数(hiredate,enrollmentdate)的日期,并将该函数存储在数据库中。当我需要计算有效日期时,我会将此函数从数据库中拉出来,执行它传递参数以获得我的有效日期。

    我的反应是寻找能够定义日期操作功能并将其集成到我的解决方案中的DSL。然而,我对适当的DSL的搜索却一无所获。

    现在我想知道CSharpCodeProvider是否可以作为解决方案的组件。 如果我从数据库中提取字符串,并通过CsharpCodeProvider编译它,我可以强制生成的代码与函数签名匹配(需要2个日期时间参数,并返回数据时间)吗?

    有没有办法确保该功能没有任何副作用?例如,No I / O.没有阅读或会话,缓存或应用程序。

2 个答案:

答案 0 :(得分:2)

请在此处查看我最近的回答:Parsing "DateTime.Now"?

基本上,您可以轻松利用像FLEE这样的现有库来解析表达式并为这些规则发出IL。如果您查看示例,可以了解如何设置要利用的用户表达式的变量。例如,您可以定义一个由一些输入变量(如HireDateEnrollmentDate)组成的“规则”,以及一个返回日期的用户表达式/谓词。如果您在链接的答案中公开DateTime成员,那么用户也可以利用这些成员。

正如一个简单的例子,没有经过测试但应该给你一个想法。

您可以设置一些自定义功能,例如获取一个月的第一天:

public static class CustomFunctions
{
    public static DateTime GetFirstDayOfMonth(DateTime date)
    {
        return new DateTime(date.Year, date.Month, 1);
    }
}

基本的FLEE设置(您必须根据需要自定义/调整)

ExpressionContext context = new ExpressionContext();

//Tell FLEE to expect a DateTime result; if the expression evaluates otherwise, 
//throws an ExpressionCompileException when compiling the expression
context.Options.ResultType = typeof(DateTime);

//Instruct FLEE to expose the `DateTime` static members and have 
//them accessible via "DateTime".
//This mimics the same exact C# syntax to access `DateTime.Now`
context.Imports.AddType(typeof(DateTime), "DateTime");
context.Imports.AddType(typeof(CustomFunctions));

//Expose your key variables like HireDate and EnrollmentDate
context.Variables["HireDate"] = GetHireDate(); //DateTime I suppose
context.Variables["EnrollmentDate"] = GetEnrollmentDate(); //DateTime I suppose

//Parse the expression, naturally the string would come from your data source
IGenericExpression<DateTime> expression = context.CompileGeneric<DateTime>(GetYourRule(), context);

DateTime date = expression.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)))"; 

答案 1 :(得分:0)

以下链接包含您所追求的内容。本质上它是一个可插入的DSL,它允许定义无限的日期安排和集合,然后传递给函数,交叉,联合等。

http://code.google.com/p/drules/