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
}