又一次遭遇“xxx类型初始值设定项引发异常”

下了个c#实现的轻量级IoC开源项目,可是在本地使用时发现一运行就捕捉到“类型初始值设定项引发异常”的异常信息,调试几次还是不能确定到底什么地方出了问题。印象中好像碰到过这种异常,初步估计是某个静态类初始化不成功引起的,但是不能肯定。

无奈打开ILSpy查看源码,发现静态初始化的地方非常多,而且代码看上去层层嵌套,类名繁多,一行一行跟上去很容易绕晕。折腾好久未果,无奈google一下,发现早就有人和我碰到一样的问题,一看投票最多的正确解决方法差点没把自己搞疯:项目中直接添加log4net.dll引用即可。

经试验,果然。

啊啊啊啊啊啊啊啊啊啊啊啊啊…

原来是log4net,竟然又是log4net。

根据个人经验,很多开源项目都使用了log4net用来记录日志,比如在使用ibatis.net、postsharp、fastdfs的c#客户端和memcached的c#实现的某客户端的时候我都碰到过这个问题。

下次碰到相同的问题能迅速查找到原因吗?能不再浪费时间吗?还能做一些更有价值的事情吗?

或者直接问是不是缺少log4net引用?kao,天晓得。

 

附:参考NLog的GetCurrentClassLogger()方法封装一个日志类

项目中使用NLog记录日志,经常在不同的服务(类库)中引用NLog.dll,然后需要按照日期和类名(和配置相关,这里略)记录一些日志,所以调用的时候通常都这么写:

private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

这样做一次两次三次当然都不会有问题,但是如果解决方案中类库较多,老是要引用dll文件同时要记录日志就在该类中写上面一行代码就会觉得不甚其烦了,所以你肯定想到要封装一下简化调用方式。

查看LogManager.GetCurrentClassLogger()它的源码,我们看到它是这样实现的:

LogManager.GetCurrentClassLogger

 

代码很简单,就是通过堆栈技术获取到某一方法的调用者的类名,实现按照类名记录日志的方法,这个和log4net中的实现方式是非常相似的。这样我们自己可以封装一个公共Logger类,通过静态方法实现NLog中的多数常见的记录日志的方法,下面给出一个记录错误日志的简单示例方法:

Logger

 

实际上这个实现中的logger还可以通过它的Name缓存,不需要每次都写:

 var stackFrame = new StackFrame(1, false);
 var logger = LogManager.GetLogger(stackFrame.GetMethod().DeclaringType.FullName);

 

毕竟反射是很耗性能的。

通常这个Logger类会封装到公共类库下,以后使用直接引用公共类库项目,记录日志直接Logger.Error形式地调用,大家自然happy了。

关于异常处理,据博客园牛人这一篇所述,捕获异常跟踪到行微软做的很不到位,作为不明真相的群众之一,我觉得还是记录一下将来要是碰到了快速解决也好。

参考:http://msdn.microsoft.com/zh-cn/library/33k1wxtt(v=vs.95).aspx

http://www.cnblogs.com/zc22/archive/2009/12/25/1631773.html

 

补充一则:理解组件和服务的区别

下面的文字来自Martin Fowler的文章Inversion of Control Containers and the Dependency Injection pattern的部分片段(Components and Services),自己参考后稍带翻译一小段并写了一点自己的理解。

原文:

Components and Services

The topic of wiring elements together drags me almost immediately into the knotty terminology problems that surround the terms service and component. You find long and contradictory articles on the definition of these things with ease. For my purposes here are my current uses of these overloaded terms.
I use component to mean a glob of software that's intended to be used, without change, by an application that is out of the control of the writers of the component. By 'without change' I mean that the using application doesn't change the source code of the components, although they may alter the component's behavior by extending it in ways allowed by the component writers.
A service is similar to a component in that it's used by foreign applications. The main difference is that I expect a component to be used locally (think jar file, assembly, dll, or a source import). A service will be used remotely through some remote interface, either synchronous or asynchronous (eg web service, messaging system, RPC, or socket.)
I mostly use service in this article, but much of the same logic can be applied to local components too. Indeed often you need some kind of local component framework to easily access a remote service. But writing "component or service" is tiring to read and write, and services are much more fashionable at the moment.

 

组件和服务的异同

如何区分“服务”(service)和“组件”(component)?
所谓“组件”是指这样一个软件单元:它将被作者无法控制的其他应用程序使用,但后者不能对组件进行修改。也就是说,使用一个组件的应用程序不能修改组件的源代码,但可以通过作者预留的某种途径对其进行扩展,以改变组件的行为。
服务和组件有某种相似之处:它们都将被外部的应用程序使用。

在我(这里的我不是指楼猪,是Martin Fowler大大,楼猪注)看来,两者之间最大的差异在于:组件是在本地使用的(例如JAR 文件、程序集、DLL、或者源码导入);而服务是要通过——同步或异步的——远程接口来远程使用的(例如web service、消息系统、RPC,或者socket)

posted on 2012-02-14 22:09  JeffWong  阅读(10420)  评论(0编辑  收藏  举报