I have a rules engine that takes a string as a name of a rule, and compares it to a string, predicate dictionary. I'm writing a rule that will compare two datetimes and return true if they match, but allow a windows of a configurable number of seconds. Ideally, I'd like for my string/predicate key value pair to look something like
{"Allow <x> seconds", AllowXSeconds}
A user applying the rule would decide they would like a 10 second window on either side of the original datetime so they would say "Allow 10 seconds" in config. I want my code to be able to to recognize that the user wants to apply the "Allow seconds" rule, then pull the "10" out so I can use it as a variable in the rule's logic. I'd rather not use regex, as the class is already built, and I don't know if I'll be allowed to refactor it in that way. I will, though, if no one has any clever ideas on how to do this. Thanks in advance, to all you smart guys and gals!
You can validate using string.StartsWith
and string.EndsWith
then use string.Substring
to get the desired value and int.TryParse
to attempt to parse the value and validate that it is an integer
string str = "Allow 10 seconds";
int result;
if (str.StartsWith("Allow ")
&& str.EndsWith(" seconds")
&& int.TryParse(str.Substring(6, str.Length - 14), out result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("Invalid");
}
Also if desired there are overloads of StartsWith
and EndsWith
that will allow for case insensitive matching as well.
This looks like a perfect candidate for regular expressions.
Here is a LINQPad program that demonstrates:
void Main()
{
var lines = new[]
{
"Allow 10 seconds",
"Allow 5 seconds",
"Use 5mb"
};
var rules = new Rule[]
{
new Rule(
@"^Allow\s+(?<seconds>\d+)\s+seconds?$",
ma => AllowSeconds(int.Parse(ma.Groups["seconds"].Value)))
};
foreach (var line in lines)
{
bool wasMatched = rules.Any(rule => rule.Visit(line));
if (!wasMatched)
Console.WriteLine($"not matched: {line}");
}
}
public void AllowSeconds(int seconds)
{
Console.WriteLine($"allow: {seconds} second(s)");
}
public class Rule
{
public Rule(string pattern, Action<Match> action)
{
Pattern = pattern;
Action = action;
}
public string Pattern { get; }
public Action<Match> Action { get; }
public bool Visit(string line)
{
var match = Regex.Match(line, Pattern);
if (match.Success)
Action(match);
return match.Success;
}
}
Output:
allow: 10 second(s)
allow: 5 second(s)
not matched: Use 5mb
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.