how to eval a statement from an xml file, in C#?

  • Thread starter Thread starter Jason Shohet
  • Start date Start date
J

Jason Shohet

I want to build a rules engine in a rules.xml page. I was thinking it
would look like this:

- Rules
- rule1 if (0 < iTime <= .5) { iFee = 15; }
- rule2 if (.5 < iTime <= 1) { iFee = 20; }
- yada yada

Now lets say in my c# code I loop thru the Rules node of rules.xml, and I
want to evaluate each rule, given an iTime that the user inputed -- lets
say its .7. I want rule2 to evaluate and say, "Oh, iTime of .7 fits into
this equation, so iFee = 20" ! But I'm not sure how to get a string from
an xml node to evaluate as if it was c# code. Is it simply the evaluate
function or something like that? Does what I'm thinking of doing make sense
at all ? :)
TY Jason Shohet
 
Jason Shohet said:
I want to build a rules engine in a rules.xml page. I was thinking it
would look like this:

- Rules
- rule1 if (0 < iTime <= .5) { iFee = 15; }
- rule2 if (.5 < iTime <= 1) { iFee = 20; }
- yada yada

Now lets say in my c# code I loop thru the Rules node of rules.xml, and I
want to evaluate each rule, given an iTime that the user inputed -- lets
say its .7. I want rule2 to evaluate and say, "Oh, iTime of .7 fits into
this equation, so iFee = 20" ! But I'm not sure how to get a string from
an xml node to evaluate as if it was c# code. Is it simply the evaluate
function or something like that? Does what I'm thinking of doing make sense
at all ? :)
TY Jason Shohet

Don't bother parsing through XML. Instead, create a serializable class that
implements what you need:

http://users.skynet.be/wvdd2/Persistence/Serialization_in__NET/serialization_in__net.html

You could implement your algorithm's rules with a simple hashtable, where
the keys are times, and the values are fees:

foreach (decimal key in ht.Keys)
{
if (iTime < key)
iFee = ht[key];
}

Then, serialize the hasthable to a file, and bob is your uncle.

Erik
 
I'm not sure how seriealizing a class, and having that class query a table
helps. I'm probably not getting it ;)

My thoughts are, I want the rules in an xml file because they can be changed
easily w/o recompiling, or going into a database etc. I can just make the
change to the rule, in the xml node. I think there's an eval statement in
C#, and if so, In the c# codebehind, I could retrieve the rules from the
xml page. I could perhaps just loop thru those retrieved rules and do:
eval (strRule) where strRule has the retrieved rule from the xml file --
like I wrote below.

- Rules
- rule1 if (0 < iTime <= .5) { iFee = 15; }
- rule2 if (.5 < iTime <= 1) { iFee = 20; }
- yada yada

My thinking is this would give me flexibility. I could write new rules,
change existing ones in the xml and there's no database involved & nothing
to compile.... Am I smoking something or am I on to something?

VR Jason Shohet
 
Comments inline.

Jason Shohet said:
I'm not sure how seriealizing a class, and having that class query a table
helps. I'm probably not getting it ;)

The point isn't so much serializing the class as deserializing it for
use in your program. Your rules (0 ... .5 -> 15, .5 ... 1 -> 20) are
serialized to an xml file, which you can change without recompiling, and
then deserialize into a simple class you can use.
My thoughts are, I want the rules in an xml file because they can be changed
easily w/o recompiling, or going into a database etc. I can just make the
change to the rule, in the xml node. I think there's an eval statement in
C#, and if so, In the c# codebehind, I could retrieve the rules from the
xml page. I could perhaps just loop thru those retrieved rules and do:
eval (strRule) where strRule has the retrieved rule from the xml file --
like I wrote below.

- Rules
- rule1 if (0 < iTime <= .5) { iFee = 15; }
- rule2 if (.5 < iTime <= 1) { iFee = 20; }
- yada yada

My thinking is this would give me flexibility. I could write new rules,
change existing ones in the xml and there's no database involved & nothing
to compile.... Am I smoking something or am I on to something?

I'm not sure where you're getting the idea of using a database from.
All you need is an xml file that contains your serialized classes.

If you sit down and think about it, I bet you'll find that there are
perhaps only two or three different rule types that your users will want to
implement.

You could probably accomplish what you want using the System.CodeDom
namespace. But the result is going to be horribly insecure (executable text
files?), and quite possibly around five to ten times as much work as
implementing two or three different kinds of business rules.

Think of what you're trying to accomplish instead of how glamorous an
idea may sound.

Erik
 
ok cool, I never thought of having just xml out on the server, and
deserializing from it. Is what you're saying:

1. create the xml that represents a class in xml
2. just deserialize it for use in the codebehind when needed

That sounds interesting -- but how do I know the format that .NET needs it
in. I mean if I have a regular xml file out there, is that enough to
serialize and grab in .NET or does it need certain header info etc. I guess
i'm insecure about this because I've only serialized to a webservice, then
deserialized to do some work, serialized to send it back again &
unserialized on the page. I've never given thought to what the xml needs
to look like before its deserialized. I guess regular xml like i was
mentioning would work?

TY again
 
But XML serialization/deserialization is meant to represent data, not logic. So I don't quite see how it would help.
 
2 options come to mind

1. If your rule structure is consistent, you could change your DOM to look something like this

<rule lbound="0" lbound-inclusive="false" ubound=".5" unbound-inclusive="true" output="15"/><rule lbound=".5" lbound-inclusive="false" ubound="1" unbound-inclusive="true" output="20"/
...

your code could then iterate through the nodes and use the attribute values to compose the logic

2. If you're looking for a more general purpose solution, you could include the code expressions in your DOM (as you showed), iterate through the DOM to write out a full C# class definition (possibly using XSLT), and use either classes in the Reflection.Emit namespace (or the Microsoft.CSharp.Compiler class) to emit an assembly that implements your logic.
 
Jason Shohet said:
ok cool, I never thought of having just xml out on the server, and
deserializing from it. Is what you're saying:

1. create the xml that represents a class in xml
2. just deserialize it for use in the codebehind when needed

That sounds interesting -- but how do I know the format that .NET needs it
in. I mean if I have a regular xml file out there, is that enough to
serialize and grab in .NET or does it need certain header info etc. I guess
i'm insecure about this because I've only serialized to a webservice, then
deserialized to do some work, serialized to send it back again &
unserialized on the page. I've never given thought to what the xml needs
to look like before its deserialized. I guess regular xml like i was
mentioning would work?

TY again

You are correct - there are a number of headers and attribute info in a
serialized xml file that you probably don't want to worry about generating
from scratch.

The best way to create the xml file is to have .NET do it for you. If
xml hasn't been generated for a class yet, generate a default instantiation
of the class. This is similar to how many programs store their user
options.

The nice thing about this approach is you never actually have to worry
about a single line of XML code yourself. Your classes effortlessly persist
themselves from one instance of the application to another.

The pseudo code would look something like this:

ON LOAD:

if (xml file exists)
deserialize my rules from xml file
else
create a default instance of my rules

ON EXIT:

serialize my rules to xml file

Erik
 
Dan,
Thanks for your advice. I thought of the first one, but its not a general
solution enough, ie, what about rules that aren't 'bound' rules, and instead
are like, "If firstname starts with 'J' then do xxx". So I figure your
second bit of advice is the way to go perhaps. The only thing I don't know
is how to evaluate the logic, that came from the XML DOM. I can get it in
my C# codebehind page, into a string variable. But how to evaluate it? Can
I just do like in javascript:

Eval (strRule1);

If not, what does that Reflection.Emit namespace do -- same thing as that
Eval?

Rgds,
Jason Shohet
 
Back
Top