0

I am trying to work a dynamic way to define conditional rules that need to apply to data in a report. What I want is to allow the end user specify the conditions in a configuration, which is then compiled and executed when the report is run.

Now if done in code, I would have something like the code below.

      public int showTopEntries{get; set;}
. . . . 

showTopEntries = showTopEntries >= totalEntries ? totalEntries : showTopEntries;

However since I would prefer to have the user provide this rule in a text file, where it is read and translated, in code. How can I parse a string of the form(below) into the statement above please?

PropertyToSet= "showTopEntries" Condition ="showTopEntries >= totalEntries" ifTrue="totalEntries" ifFalse="showTopEntries"

Ultimately, I would like to have users defined rules in the form

<IfCondition>
    <WhenTrue><\WhenTrue>
    <WhenFalse>
        <IfCondition>
            <WhenTrue>
                <IfCondition>
                    . . . . .
                <\IfCondition>
            <\WhenTrue>
        <\IfCondition>
    <\WhenFalse>
<\IfCondition>

Basically, if I have an object

public class PersonDetail { public String Name{get; set;} public String Description{get; set;} public String Age{get; set;} public Boolean Alive{get; set;} public MaritalStatus MaritalStatus {get; set;} public Address Address{get; set;} }

And I needed to apply a conditional replace of, say a substring, the name, using the following expression

  public static class  DetailExtender
     {
          public static void EvaluateConditionalFieldRule(this PersonDetail Detail, String PropertyToEvaluate, String ConditionalExpression, List<String> parameters, String IfTrue, String ifFalse)
          {
               var property =  Detail.GetType().GetProperties().Where(x=>x.Name == PropertyToEvaluate);
               if (property == null)
                    throw new InvalidDataException("Please specify a valid  Detail property name for the evaluation.");
               //put together the condition like so 

               if (Detail.AsQueryable().Where(ConditionalExpression, parameters).Count() > 0)
               {
                    // property.Value = IfTrue;
               }
               else
               {
                    property.Value = ifFalse;
               }

          }
}

Thanks in advance for your suggestions.

Kobojunkie
  • 6,375
  • 31
  • 109
  • 164
  • How does parsing code from a file have to do with LINQ? – Servy Sep 06 '13 at 15:14
  • So what are the allowable entries here? Are people able to write any arbitrary C# code, are you limiting certain operations, is this just expressions, or what? – Servy Sep 06 '13 at 15:14
  • It's also worth mention the very, very, very great security concerns here of executing code provided as text by an end user. It's the epitome of an injection vulnerability. – Servy Sep 06 '13 at 15:16
  • possible duplicate of [Expression.Lambda and query generation at runtime, simplest "Where" example](http://stackoverflow.com/questions/8315819/expression-lambda-and-query-generation-at-runtime-simplest-where-example) – Hamlet Hakobyan Sep 06 '13 at 15:19
  • This is not a simple requirement. You essentially want to build a simple scripting language. For end user report building, there's already a number of tools available to plug into your application which have far more powerful expression building capabilities. – rdans Sep 06 '13 at 18:42

1 Answers1

1

Look at Dynamic LINQ, it provides extensions that let you pass a string to a Where(string) extension, and it builds the predicate dynamically for you:

string filter = MyConfig.GetString("Condition");
// filtered string is "Condition ="showTopEntries >= totalEntries"
var filtered = dataSource.Where(filter);
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The datasource in this case is a single object that has a couple of properties. I was wondering if there is a class that simply does If-then-else evaluation of this kind. I would like to flexibility of nesting my conditions and having those considered as well. – Kobojunkie Sep 06 '13 at 15:25
  • @Kobojunkie There's no path to "simplicity" there: converting a string to an expression that you can evaluate requires parsing and dynamic mapping. Essentially, one needs to rebuild a small portion of the C# compiler for use at runtime. Dynamic LINQ does that for you. – Sergey Kalinichenko Sep 06 '13 at 15:31
  • OK. So how do I apply this to querying a single object please? – Kobojunkie Sep 06 '13 at 18:17
  • @Kobojunkie Use `new[] {myObject}.Where(conditionString).SingleOrDefault()`. It would return the object if the condition is met, and `null` otherwise. – Sergey Kalinichenko Sep 06 '13 at 18:19
  • I am using Dynamic lib but I still am not getting the assignment portion as I expect. Essentially, I would like to do string manipulation on the properties of the objects that my query returned. A way of formating, resetting, etc. – Kobojunkie Sep 11 '13 at 14:49
  • @Kobojunkie I am not sure if dynamic linq is suitable for that: manipulating the results the way the compiler does generally requires creating anonymous types, which can be done only at compile-time. – Sergey Kalinichenko Sep 11 '13 at 15:04