Posted on 2005-12-03 08:31
实战演练 阅读(226)
评论(0) 编辑 收藏 引用 所属分类:
ASP.NET
最近研究ASP.NET Forums,越来越多的感到MS的高手们就是高手,他们能够合理的利用缓存来提高访问效率,并且提供了很多方便,譬如今天要研究的 显示语言和错误信息就是Cache的一个典型应用。
在ASP.NET Forums中,将语言信息,错误提示等全部放到单独的XML中,作为资源文件,这样就很容易实现多语言界面。(这我想到了以前我们做ASP开发的时候,都是将语言写入数据库,登陆的时候根据用户选择,一次性写入Application,从而实现多语言支持,这样大量的写入Application会导致系统资源的极大浪费…)。而在ASP.NET Forums里就是利用缓存的文件信赖实现了很多东东。
注:CacheDependency :ASP.NET 能够在放入缓存中的项与文件系统中的文件之间创建相关性。 如果相关性所针对的文件更改,ASP.NET 会自动将相关项从缓存中删除。
打开位于Components目录下的ResourceManager.cs我们可以看到。
代码如下:
1 public class ResourceManager ...{
2
3 // 枚举类型,表示是字符串还是错误信息
4 enum ResourceManagerType ...{
5 String,
6 ErrorMessage
7 }
8
9 // 读取支持语言,支持语言信息存放到键值对集合中,并显式声明
10 public static NameValueCollection GetSupportedLanguages () ...{
11 ForumContext forumContext = ForumContext.Current;
12 NameValueCollection supportedLanguages;
13 string cacheKey = "Forums-SupportedLanguages";
14 // 还是先在缓冲里面找, 如果过期或者信赖项改变, 就重新读取一次
15 if (forumContext.Context.Cache[cacheKey] == null) ...{
16
17 // 得到 Languages.xml 文件的绝对地址, 并将它作为信赖项插入缓冲
18 string filePath = forumContext.Context.Server.MapPath("~" + ForumConfiguration.GetConfig().ForumFilesPath + "/Languages/languages.xml");
19//通过System.Web.Caching.CacheDependency把缓存中的内容和文件相关联起来,如果源始文件改动,就会更
20新缓存。
21 CacheDependency dp = new CacheDependency(filePath);
22 supportedLanguages = new NameValueCollection();
23 // 读这个XML文档
24 XmlDocument d = new XmlDocument();
25 d.Load( filePath );
26
27 // 根结点是 root , 只读非注释结点
28 foreach (XmlNode n in d.SelectSingleNode("root").ChildNodes) ...{
29 if (n.NodeType != XmlNodeType.Comment) ...{
30 // 将语言的全称对应简写加入到键值对集合中. 如 U.S. English 和 en-US.
31 supportedLanguages.Add(n.Attributes["name"].Value, n.Attributes["key"].Value);
32 }
33 }
34 // 将键值对集合和它的信赖项 (Languages.xml) 加入到缓冲中
35 forumContext.Context.Cache.Insert(cacheKey, supportedLanguages, dp, DateTime.MaxValue, TimeSpan.Zero);
36 }
37 return (NameValueCollection) forumContext.Context.Cache[cacheKey];
38 }
39
40 // 这是一个内部方法, 用来读另外两个资源文件 Resources.xml 和 Messages.xml,
41 // 它根据不同的语言进入不同的目录, 根据不同的类型 字符串 还是 错误消息 来读不同的文件,
42 // 并放入 target 指示的哈希表
43 private static void LoadResource (ResourceManagerType resourceType, Hashtable target, string language, string cacheKey) ...{
44 ForumContext forumContext = ForumContext.Current;
45 // 根据语言得到这个文件的绝对路径.
46 string filePath = forumContext.Context.Server.MapPath("~" + ForumConfiguration.GetConfig().ForumFilesPath + "/Languages/" + language + "/{0}");
47 // 根据类型读不同的文件
48 switch (resourceType) ...{
49 case ResourceManagerType.ErrorMessage:
50 filePath = string.Format(filePath, "Messages.xml");
51 break;
52 default:
53 filePath = string.Format(filePath, "Resources.xml");
54 break;
55 }
56 CacheDependency dp = new CacheDependency(filePath);
57 XmlDocument d = new XmlDocument();
58 try ...{
59 d.Load( filePath );
60 } catch ...{
61 return;
62 }
63
64 // 遍历文档, 将相应值放入哈希表
65 foreach (XmlNode n in d.SelectSingleNode("root").ChildNodes) ...{
66 if (n.NodeType != XmlNodeType.Comment) ...{
67 switch (resourceType) ...{
68 case ResourceManagerType.ErrorMessage:
69 ForumMessage m = new ForumMessage(n);
70 target[m.MessageID] = m;
71 break;
72 case ResourceManagerType.String:
73 if (target[n.Attributes["name"].Value] == null)
74 target.Add(n.Attributes["name"].Value, n.InnerText);
75 else
76 target[n.Attributes["name"].Value] = n.InnerText;
77 break;
78 }
79 }
80 }
81 // 不同的语言应该有不同的缓冲时间, 默认语言应该一直被放在缓冲区
82 // 直到信赖项改变, 而非默认语言只被缓冲一个小时.
83 DateTime cacheUntil;
84 if( language == ForumConfiguration.GetConfig().DefaultLanguage ) ...{
85 cacheUntil = DateTime.MaxValue;
86 }
87 else ...{
88 cacheUntil = DateTime.Now.AddHours(1);
89 }
90 forumContext.Context.Cache.Insert(cacheKey, target, dp, cacheUntil, TimeSpan.Zero);
91 }
92
93 // 这个方法根据用户语言和资源类型返回缓冲中的一个哈希表
94 private static Hashtable GetResource (ResourceManagerType resourceType) ...{
95 ForumContext forumContext = ForumContext.Current;
96 Hashtable resources;
97 string defaultLanguage = ForumConfiguration.GetConfig().DefaultLanguage;
98 string userLanguage = Users.GetUser().Language;
99 string cacheKey = resourceType.ToString() + defaultLanguage + userLanguage;
100 // 保证用户至少有一种语言
101 if (userLanguage == "")
102 userLanguage = defaultLanguage;
103 // 先看缓冲里有没有这个哈希表
104 if (forumContext.Context.Cache[cacheKey] == null) ...{
105 resources = new Hashtable();
106 // 先加载英文版本的
107 LoadResource(resourceType, resources, "en-US", cacheKey);
108 // 再根据用户的选择更改
109 if ("en-US" != userLanguage)
110 LoadResource(resourceType, resources, userLanguage, cacheKey);
111 }
112 return (Hashtable) forumContext.Context.Cache[cacheKey];
113 }
114 // 这个方法得到 Resources.xml 中和 name 对应的字符串
115 public static string GetString(string name) ...{
116 Hashtable resources = GetResource (ResourceManagerType.String);
117 if (resources[name] == null) ...{
118 throw new ForumException(ForumExceptionType.ResourceNotFound, "Value not found in Resources.xml for: " + name);
119 }
120 return (string) resources[name];
121 }
122 // 如上面那个方法, 它返回错误消息对象, 它的键值是一个整数,
123 // 而 ForumExceptionType 是一个枚举类型, 它的整数值和 ForumMessage
124 // 的 MessageID 对应.
125 public static ForumMessage GetMessage (ForumExceptionType exceptionType) ...{
126 Hashtable resources = GetResource (ResourceManagerType.ErrorMessage);
127 if (resources[(int) exceptionType] == null) ...{
128 throw new ForumException(ForumExceptionType.ResourceNotFound, "Value not found in Messages.xml for: " + exceptionType);
129 }
130 return (ForumMessage) resources[(int) exceptionType];
131 }
132 }