从写组件说Xml——改良(六)

1.提出问题

    前面五篇说了如何实现,但是如果xml配置错了怎么办哪?

    首先,利用Xsd,已经可以保证大部分xml的类型不会出错,但是,之前把Expression设计为弱类型的,也就意味着Expression不对其返回的类型负责,这是第一个在xml运行时存在的不稳定因素。

    第二,变量本身也有不安全因素,首先变量名本身就非常容易出现书写错误,其次,变量名本身也是弱类型的,不到运行时,根本不知道里面到底放的是什么。

    第三,参数(Parameter)。参数是在IGeneratorEngine的Generate方法输入的,因此,这里Xml配置中的参数是依赖于c#的输入的,而这个也是必须到运行时才能知道的。

    第四,CliFunction。这个PInvoke是为Xml调用.net方法而设计的,那么自然也就会有各种不稳定因素会出现。

    第五,实现本身的缺陷导致的问题。

2.改良日志

    要排除以上运行时问题,最简单的方法就是记录日志。说到日志,是不是马上就想到:

  • Log4Net
  • Enterprise Library - Logging Application Block

    没错,这是两个用的最多的日志工具,但是,它们也是通用的日志工具,并不适合记录Xml的场合(至少,没法帮助我们直接定为到Xml的哪一行出的错)。

    所以,需要把日志服务包装一下:

image

    现在只需要在实现TraceErrorCore的时候多添加一个Xml的调用堆栈即可。既然有调用堆栈,那就先要定义:

image

    然后再定义调用堆栈:

image

    然后再重写ToString方法:

image

    然后准备一套关于Xml调用堆栈的扩展方法:

image

    剩下来的就是让那些实现类额外实现一个IXmlFunction,例如:

image

    这样就可以让每一个结构被调用时,把调用信息写入调用堆栈,并且可以在GetAdditionalInformation添加其它相关的参数信息。

    现在再回到TraceService,可以进一步把Core方法实现了(为了避免牵涉到具体的日志工具,就用.net自带的Trace来记录):

image

    如果context为空,那就意味着当前不在Xml配置相关的运行状态,否则就记录相关的Xml调用堆栈。

    最后,把所有需要记录日志的地方替换成使用TraceService。现在Xml调用堆栈已经都准备好了。

3.进一步改良日志

    前一节已经可以把日志定位到行为了,但是,这样依然不能知道到底是Xml的哪一行哪一列出了错。当然反序列化本身无法提供这样的信息。

    这里,先引入一个接口:IXmlLineInfo

    用Reflector来看一下哪些类实现了这个接口:

image 

3.1 Linq to Xml

    首先是Linq to Xml的XObject实现了这个接口,因此先大概写一个XLinq的Loader:

image

    因为IXmlLineInfo接口是只读的,因此,需要再定义一个写入这些行信息的接口:

image

    然后让Slide实现这个接口:

image

    别忘了给新添加的公共属性添加XmlIgnore特性,否则会影响Xml序列化的行为。

    再次回到XLinqLoader,现在需要额外添加IXmlLineInfo的信息:

image

    如此就可以完成了一个使用Linq to Xml的Loader。

3.2 XPathDocument

    再次看一下实现IXmlLineInfo的实现类:

image

    这次关注一下选中的这个类,当然这个类型不是公开的,不过可以用Reflector分析一下:

image

    该分析指出,这个类是由XPathDocument的CreateNavigator方法来创建实例的,进一步用Reflector查看这个方法:

image

    也就是说,CreateNavigator返回的就是这个类型的一个实例。

    那么再写一个利用XPathDocument的Loader:

image

    (XPathDocument的Navigator是只读的,所有修改内容的方法都将抛出NotSupportedException

3.3 其它

    除了上面介绍的两个方法,也可以用XmlReader方式读取,用XmlReader.Create方法创建的一个XmlReader的实例,然后强转成IXmlLineInfo就可以了。

4.改良日志提供LineInfo

    第二节的日志已经提供了Xml的相关信息,而在第三节又提供了LineInfo,那么在这一节,就把LineInfo写到日志里面,再次改造一下XmlCallStack的ToString方法:

image

    这样Xml的日志已经基本完成了。


上一篇:从写组件说Xml——实现(五)


原文地址:https://www.cnblogs.com/vwxyzh/p/1578466.html