实战演练

一步一个脚印
posts - 9, comments - 14, trackbacks - 0, articles - 17
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

ASP.NET Forums 资源文件缓存管理(转载)

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    }

只有注册用户登录后才能发表评论。