C语言的科学和艺术

C语言的科学和艺术

这本书是国内外几个著名大学的C语言课本,除了C语言的基本语法外,着重引导读者开始使用一个语言编写程序的过程。

不过如果你已经有了较多开发经验,那还是不要看这本书吧,呵呵。

优点

  • 深入浅出,易学好懂;
  • 着重引导了程序开发的基本规范和思路,对初学者非常重要;
  • 通过作者自己写的库隐藏了部分C语言比较烦琐难懂的语法细节,使初学者更容易上手;

缺点

  • 不少代码不使用C标准库;
  • 比较罗嗦一点;
  • 缺乏部分语法细节;

优点和缺点其实只是对不同的人而言,书本身是很好的。这本书非常适合没有语言开发经验或者自学缺乏良好开发基础的人学习使用,如果是这样的读者,就不要犹豫了,很值!

利用.NET的XMl序列化解决系统配置问题

在Web系统开发中,我们经常需要读取和设置一些系统配置项,常见的例如数据库连接字符串、上传路径等等。

在最初的ASP系统中,比较常用的方法是将值保存为Application或Session变量;在Asp.net系统中,目前比较常见的简单方法是把相应的配置项写入Web.Config中,例如




	
	...
	

	
		
	

然后在程序中通过如下方式读取

string connString = ConfigurationSettings.AppSettings["ConnectionString"];

这种方法在系统规模较小复杂度较低的时候也不失为一种简单明了的轻量级方法,不过如果系统较复杂,配置项会较多,同时我们需要按不同模块对配置进行划分,并且还希望能以面向对象方法来对其进行封装,那么如果仍然采用这种过于简化方式就不太合时宜了。


下面,我讲述一下通过XML类序列化解决系统配置问题的方法。

关于XML类序列化和反序列化(另外一种描述是串行化和并行化)的技术细节,大家可以查看MSDN了解;这里简单讲两句,XML序列化是把一个对象序列化到XML文档的过程,反序列化则是从XML输出中重新创建原始状态的对象。

直观表现就是如下图模式

看了这个图,就很清楚了,通过序列化,可以采用面向对象的方法,非常自然和方便的读取和设置系统配置;.NET Framework承担了对象和XML文件映射工作,我们只需要简单的使用就OK。下面我们讲一下具体内容。

上面图示已经表明,首先需要一个XML配置文件,格式内容如上图,具体配置项可以自行增减。

然后我们需要编写一个类,如上图所示;特殊的一点,为了使类能够实现XML序列化,需要在类的所有属性声明前添加属性信息XmlElement,如下所示。

[XmlElement]
public string ConnectionString
{
   get { return connectionString; }
   set { connectionString = value; }
}

由于AppConfig类本身没有实现方法,因此我们需要一个配置类AppConfigSetting.cs。类的结构很简单,只需要两个静态方法,Get()获取AppConfig对象,Save()保存AppConfig对象。

另外,我们需要在 Web.Config中添加该XML配置文件的地址。




  


public class AppConfigSetting
{
   //获取配置对象
   public static AppConfig Get()
   {
      //尝试获取缓存中的对象
      AppConfig config = (AppConfig)HttpContext.Current.Cache["AppConfig"];

      //如果缓存中没有该配置对象,则直接获取对象
      if (config == null)
      {
         //新建序列化对象并指定其类型
         XmlSerializer serial = new XmlSerializer(typeof(AppConfig));

         try
         {
            string file = HttpContext.Current.Server.MapPath(GetFile());

            //读取文件流
            FileStream fs = new FileStream(file, FileMode.Open);

            //文件流反序列化为对象
            config = (AppConfig)serial.Deserialize(fs);

            fs.Close();

            //将对象加入到缓存中
            HttpContext.Current.Cache.Insert("AppConfig",
                        config, new CacheDependency(file));
         }
         catch (System.IO.FileNotFoundException)
         {
            config = new AppConfig();
         }
      }

      return config;
   }

   //保存配置对象
   public static void Save(AppConfig config)
   {
      string file = HttpContext.Current.Server.MapPath(GetFile());
      XmlSerializer serial = new XmlSerializer (typeof(AppConfig));

      FileStream fs = new FileStream(file, FileMode.Create);

      //对象序列化为文件
      serial.Serialize(fs, config);
      fs.Close();
   }

   //获取配置文件路径
   private static string GetFile()
   {
      string path = (string)HttpContext.Current.Cache["FilePath"];

      if (path == null)
      {
         path=ConfigurationSettings.AppSettings["AppConfigPath"];
         HttpContext.Current.Cache["FilePath"] = path;
      }
      return path;
   }

}

类的使用非常简单,基本方式如下

//代码仅为使用演示
AppConfig config = AppConfigSetting.Get();

string connString = config.ConnectionString;

...

config.ConnectionString = connString;
AppConfigSetting.Save(config);

看到这样的代码,不禁有令人赏心悦目之感;相对于原来的直接读取AppSetting,可谓解脱矣! :)

OK,就此结束了。这篇文章只涉及对象序列化的非常简单的应用,没有涉及太多的技术原理和细节,大家要深入了解请参考MSDN。

希望文章能对大家有所补益和启发。 :)

测试源代码工程文件下载(Visual Studio.net 2003)

CSS设计器代码参考.1

这里对前面讲的CSS设计器系统关键代码作一些小结,如果没有看过前面文章请先参看前文

解析CSS样式文件

这段代码主要作用是把CSS文件分解为多个样式类,并按名称/文本属性生产ClassItem对象,并保存在一个ArrayList(cssList)中(C#代码)

//读取文件
 FileInfo theSource= new FileInfo (@m_filePath);
 StreamReader reader = theSource.OpenText();

 //将文件流转化为文本
 m_cssText = reader.ReadToEnd();
 reader.Close();

 //定义CSS文本分割符
 char[] delimiters = new char[] { '{','}'};
 int iCheck = 1;string className = null;

 //将文本转化为ArrayList
 foreach ( string substring in m_cssText.Split(delimiters))
 {
     if (iCheck%2==0)
         //当iCHeck为偶数时,字符串为样式属性内容 
         //将解析的样式名和属性作为ClassItem对象存入cssList        
         cssList.Add( new ClassItem ( className, substring.Trim() ) );

     else
         //当iCHeck为奇数时,字符串为样式名,暂存 
         className = substring.Trim(); iCheck++;
 }

交互界面构建

交互界面由Javascript通过XmlDocument读取Xml文件动态生成。

首先要读取XML文件,然后遍历整个XML文件,先遍历样式分类,再对每个分类遍历其下的所有样式属性。比较关键的代码是对XML的遍历,下面是对样式分类的遍历代码。

//LoadXML是XML文件读取函数
var dom = LoadXML("css.xml");

//通过XPath和selectNodes方法返回一个XMLDOMNodeList对象
var oNode = dom.selectNodes("//Category/Name");

//获取该对象长度,即XML文档中该路径节点的数量
var intCategory = oNodes.length;
for (i=0; i<intCategory; i++)
{
//获取集合中的节点
oNode = oNodes.nextNode;

if (oNode != null)
{
//样式分类界面构建代码-略 ……
}
}

样式输入控件构建函数,该函数作用是根据XPath路径查询XML定义,生成交互控件

function BuildInput ( path )
{
var str="";
var aNode=null;
var attValue=null;

//通过selectSingleNode返回符合条件的第一个节点 
var actNode = dom.selectSingleNode(path+"ActionType");
var nameNode = dom.selectSingleNode(path+"CssName");

//如果属性为选择输入,则读取SelectItems,并构建select控件 
if (actNode.text=="select")
{
str += "<select id='"+nameNode.text+"' name='"+nameNode.text+"'class='eSelect'>";

//查询该项的所有选择列表项 
var itemsNodes = dom.selectNodes (path+"SelectItems/Item");
str += "<option value='-1'>未设置</option>";
for (ii=0;ii<itemsNodes.length;ii++){
aNode = dom.selectSingleNode (path+"SelectItems/Item["+ii+"]");

//如果该项含有Name属性则在列表中显示Name属性值
attValue = aNode.getAttribute("Name")
var txtNode = dom.selectSingleNode (path+"SelectItems/Item["+ii+"]");
if (attValue==null)
str += "<option value='"+txtNode.text+"'>"+txtNode.text+"</option>";
else
str += "<option value='"+txtNode.text+"'>"+attValue+"</option>";
}
str += "</select>";
}
else
//如果属性为其他模式,则构建input输入,设置class属性为ActionType
{
str = "<input name='"+nameNode.text+"' id='"+nameNode.text+"' class='"+actNode.text+"'>";
}

return(str);
}