Using CSharpCodeProvider to allow user created functions

后端 未结 2 448
悲哀的现实
悲哀的现实 2021-01-25 06:35

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.<

2条回答
  •  抹茶落季
    2021-01-25 07:22

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

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

    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 expression = context.CompileGeneric(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)))"; 
    

提交回复
热议问题