Sample

<!-- during normal execution only log Info messages -->
<defaultFilter>level >= LogLevel.Info</defaultFilter>
<!-- if there is at least one error, log everything from trace level -->
<when exists="level >= LogLevel.Error" filter="level >= LogLevel.Trace" />

实现将字符串转换成表达式进行逻辑判断,然后做出相应的动作。这个过程的实现使用Condition Expression。

从简单的例子开始:

public void BooleanOperatorTest()
{
AssertEvaluationResult(false, "false or false");
AssertEvaluationResult(true, "false or true");
AssertEvaluationResult(true, "true or false");
AssertEvaluationResult(true, "true or true");
AssertEvaluationResult(false, "false and false");
AssertEvaluationResult(false, "false and true");
AssertEvaluationResult(false, "true and false");
AssertEvaluationResult(true, "true and true");
AssertEvaluationResult(false, "not true");
AssertEvaluationResult(true, "not false");
AssertEvaluationResult(false, "not not false");
AssertEvaluationResult(true, "not not true");
}

输入的是字符串false or false,我们希望的结果是得到false,大概的过程是这样的:

CondtionParser

 /// <summary>
/// Condition parser. Turns a string representation of condition expression
/// into an expression tree.
/// </summary>
public class ConditionParser

第一步就是初始化这个Parser

var parser = new ConditionParser(new SimpleStringReader(expressionText), configurationItemFactories);

顺带初始化了tokenizer

    private ConditionParser(SimpleStringReader stringReader, ConfigurationItemFactory configurationItemFactory)
{
this.configurationItemFactory = configurationItemFactory;
this.tokenizer = new ConditionTokenizer(stringReader);
}

构造函数里直接取到了第一个token false

    public ConditionTokenizer(SimpleStringReader stringReader)
{
this.stringReader = stringReader;
this.TokenType = ConditionTokenType.BeginningOfInput;
this.GetNextToken();
}

获取的过程也比较的简单,一个接一个的读入char,遇到非指定的字符即停止

private void ParseKeyword(char ch)
{
int i;
this.TokenType = ConditionTokenType.Keyword; StringBuilder sb = new StringBuilder(); sb.Append((char)ch); this.ReadChar(); while ((i = this.PeekChar()) != -1)
{
if ((char)i == '_' || (char)i == '-' || char.IsLetterOrDigit((char)i))
{
sb.Append((char)this.ReadChar());
}
else
{
break;
}
} this.TokenValue = sb.ToString();
}

这里有一系列比较复杂的表达式树生成的过程:

private ConditionExpression ParseBooleanOr()
{
ConditionExpression expression = this.ParseBooleanAnd(); while (this.tokenizer.IsKeyword("or") || this.tokenizer.IsToken(ConditionTokenType.Or))
{
this.tokenizer.GetNextToken();
expression = new ConditionOrExpression(expression, this.ParseBooleanAnd());
} return expression;
}

最后拿到的表达式树是这样的:

左右的表达式为ConditionLiteralExpression

     private ConditionExpression ParseLiteralExpression()
{
//...... if (this.tokenizer.TokenType == ConditionTokenType.Keyword)
{
string keyword = this.tokenizer.EatKeyword(); if (0 == string.Compare(keyword, "level", StringComparison.OrdinalIgnoreCase))
{
return new ConditionLevelExpression();
} if (0 == string.Compare(keyword, "logger", StringComparison.OrdinalIgnoreCase))
{
return new ConditionLoggerNameExpression();
} if (0 == string.Compare(keyword, "message", StringComparison.OrdinalIgnoreCase))
{
return new ConditionMessageExpression();
} if (0 == string.Compare(keyword, "loglevel", StringComparison.OrdinalIgnoreCase))
{
this.tokenizer.Expect(ConditionTokenType.Dot);
return new ConditionLiteralExpression(LogLevel.FromString(this.tokenizer.EatKeyword()));
} if (0 == string.Compare(keyword, "true", StringComparison.OrdinalIgnoreCase))
{
return new ConditionLiteralExpression(true);
}

再来个例子:

public void ConditionMethodsTest()
{
AssertEvaluationResult(true, "starts-with('foobar','foo')");
AssertEvaluationResult(false, "starts-with('foobar','bar')");
AssertEvaluationResult(true, "ends-with('foobar','bar')");
AssertEvaluationResult(false, "ends-with('foobar','foo')");
AssertEvaluationResult(0, "length('')");
AssertEvaluationResult(4, "length('${level}')");
AssertEvaluationResult(false, "equals(1, 2)");
AssertEvaluationResult(true, "equals(3.14, 3.14)");
AssertEvaluationResult(true, "contains('foobar','ooba')");
AssertEvaluationResult(false, "contains('foobar','oobe')");
AssertEvaluationResult(false, "contains('','foo')");
AssertEvaluationResult(true, "contains('foo','')");
}

这里出现了一些条件方法starts-with,ends-with,equals,contains,可以通过这些操作,当log的message包含特定的字符串的时候才写日志

[ConditionMethod("starts-with")]是以属性反射的方式在初始化的时候加载的。

在parse的过程中,多一步判断是否是ConditionMethods并创建实例

private ConditionMethodExpression ParsePredicate(string functionName)
{
try
{
var methodInfo = this.configurationItemFactory.ConditionMethods.CreateInstance(functionName);
return new ConditionMethodExpression(functionName, methodInfo, par);
}
catch (Exception exception)
{
if (exception.MustBeRethrown())
{
throw;
} throw new ConditionParseException("Cannot resolve function '" + functionName + "'", exception);
}
}

那么怎么知道该字符串是否是ConditionMethods呢?这里还是简单从左到右一个个的吃字符。

public string EatKeyword()
{
if (this.TokenType != ConditionTokenType.Keyword)
{
throw new ConditionParseException("Identifier expected");
} string s = (string)this.TokenValue;
this.GetNextToken();
return s;
}

当出现特殊的char时候做出判断。

     private static ConditionTokenType[] BuildCharIndexToTokenType()
{
CharToTokenType[] charToTokenType =
{
new CharToTokenType('(', ConditionTokenType.LeftParen),
new CharToTokenType(')', ConditionTokenType.RightParen),
new CharToTokenType('.', ConditionTokenType.Dot),
new CharToTokenType(',', ConditionTokenType.Comma),
new CharToTokenType('!', ConditionTokenType.Not),
new CharToTokenType('-', ConditionTokenType.Minus),
};

最新文章

  1. python之类介绍
  2. 基于HTML5的Drag and Drop生成图片Base64信息
  3. Greedy:Stall Reservations(POJ 3190)
  4. 双系统重装windows后修复UBUNTU的GRUB
  5. 推荐:一个个人开发者搞app赚钱之后的总结!有图有真相。
  6. [译]GotW #6a: Const-Correctness, Part 1
  7. java特点
  8. Android中的TextView实现多行显示省略号
  9. 你知道OneNote的OCR功能吗?office lens为其增大威力,中文也识别
  10. LoonAndroid自动检测输入框 --- Author: rose &amp;&amp; lvyerose@163.com
  11. Js中有关变量声明和函数声明提升的问题
  12. Python中的引号用法总结
  13. K - 迷宫问题 POJ - 3984
  14. Spring(四):Spring整合Hibernate,之后整合Struts2
  15. POE 供电
  16. mysql varchar存储最大
  17. 15款css3鼠标悬停图片动画过渡特效
  18. golang 的 buffered channel 及 unbuffered channel
  19. grafana + influxdb + telegraf
  20. golang爬取免费代理IP

热门文章

  1. nginx 下 bootstrap fa 字体异常问题
  2. dtw算法
  3. 【Networking】flannel,pipework,weave,udp,vxlan,ovs等资料
  4. 【GoLang】GoLang for 中有多个循环变量怎么处理?
  5. C#系统委托之Action And Func
  6. Delphi 多步操作产生错误,请检查每一步的状态值
  7. WinAPI: ShellExecute - 打开外部程序或文件
  8. Greedy:Bound Found(POJ 2566)
  9. CSS3实现圆角效果
  10. IOS - NSURLSession