使用CSHARP codeProvider允许用户创建功能功能、用户、CSHARP、codeProvider

2023-09-03 07:00:44 作者:放荡不羁就是边爷i

我有一个现有的asp.net(C#)应用程序。我需要为用户提供一种方式来创建软包装规则来计算给定HIREDATE和enrollmentdate生效日期。

I have an existing asp.net (c#) application. I need to provide users with a way to create flexibles rules to calculate an effective date given a hiredate and an enrollmentdate.

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

Some examples of rules that might be used:

HIREDATE或enrollmentdate后来的 在雇用日期+ 90天 月份的入学日期后的第一个 如果报名日期是本月15日之前,则该生效日期是下个月的1日。如果它是在15或后,它的该月的第一后

我开始了与少数偏移字段(日偏移,偏移一个月,等...),但我遇到了新的要求,我逐渐认识到目前的方式不够灵活。

I started out with a handful of offset fields (day offset, month offset, etc...), but as I come across new requirements, I'm coming to realize the current approach isn't flexible enough.

我想这样做是允许最终用户定义的函数返回给定的两个参数(HIREDATE,enrollmentdate)日期和存储功能的数据库。当我需要计算EFFECTIVEDATE我拉这个功能从数据库中执行它传递的参数,以获得我的EFFECTIVEDATE。

What I would like to do is allow the end user to define a function that returns a date given two parameters (hiredate, enrollmentdate), and store that function in the database. When I need to calculate the effectivedate I'd pull this function out of the database execute it passing in the parameters to get my effectivedate.

我的intial反应是寻找一个DSL,让我来定义日期操作功能,并集成了到我的解决方案。但是我寻找一个合适的DSL已经变成了什么。

My intial reaction was to look for a DSL that would allow me to define date manipulation functions and integrate that into my solution. However my search for an appropriate DSL has turned up nothing.

现在我想知道CSHARP codeProvider是否会作为一个组件的解决方案。 如果我拉一个字符串,从数据库中,并通过Csharp的codeProvider编译它,我可以强制执行所产生的code匹配的函数签名(需要2日期时间参数,并返回一个DATATIME)?

Now I am wondering whether CSharpCodeProvider might work as a component to the solution. If I pull a string out of a database, and compile it via CsharpCodeProvider, can I enforce that the resulting code matches a function signature (takes 2 datetime parameters, and returns a datatime)?

有没有一种方法,以确保功能没有任何副作用?例如,没有I / O。没有阅读或会议,高速缓存或应用程序。

Is there a way to ensure that the function doesn't have any side effects? For example, No I/O. No reading or session, cache, or application.

推荐答案

在这里看到我的最新答案是:的解析" DateTime.Now"?

See my recent answer here: Parsing "DateTime.Now"?

从本质上讲,你可以轻松地利用如现有的库FLEE 解析EX pressions并发出IL这些规则。如果你看一看的例子,你可以看到如何设置变量用户EX pressions杠杆。例如,您可以定义一个规则,它由一些输入变量(如雇佣日期 EnrollmentDate ),并用户EX pression / predicate返回的日期。如果暴露的DateTime 成员就像我在链接的答案,那么用户就可以利用这些为好。

Essentially, you can easily leverage an existing library like FLEE to parse expressions and emit IL for these rules. If you take a look at the examples, you can see how to set up variables for the user expressions to leverage. For example, you may define a "rule" that consists of some input variables (like HireDate or EnrollmentDate), and a user expression/predicate that returns the date. If you expose the DateTime members like I have in the linked answer, then users can leverage those as well.

就像一个简单的例子,没有测试,但应该给你一个想法。

Just as a quick example, not tested but should give you an idea.

您可以设置一些自定义的功能,帮助,喜欢把自己一个月的第一天:

You can setup some custom functions to help, like getting the first day of a month:

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

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

A basic FLEE setup (you'll have to customize/tweak as necessary)

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();

那么你的规则可能是这样的:

Then your rules might look like:

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)))";