1 namespace System.Web.Mvc {
3 using System.Collections.Generic;
4 using System.Diagnostics.CodeAnalysis;
7 using System.Reflection;
8 using System.Web.Mvc.Resources;
11 // Processes files with this format:
13 // <typeCache lastModified=... mvcVersionId=...>
14 // <assembly name=...>
15 // <module versionId=...>
21 // This is used to store caches of files between AppDomain resets, leading to improved cold boot time
22 // and more efficient use of memory.
24 internal sealed class TypeCacheSerializer {
26 private static readonly Guid _mvcVersionId = typeof(TypeCacheSerializer).Module.ModuleVersionId;
28 // used for unit testing
30 private DateTime CurrentDate {
32 return CurrentDateOverride ?? DateTime.Now;
36 internal DateTime? CurrentDateOverride {
41 [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is an instance method for consistency with the SerializeTypes() method.")]
42 public List<Type> DeserializeTypes(TextReader input) {
43 XmlDocument doc = new XmlDocument();
45 XmlElement rootElement = doc.DocumentElement;
47 Guid readMvcVersionId = new Guid(rootElement.Attributes["mvcVersionId"].Value);
48 if (readMvcVersionId != _mvcVersionId) {
49 // The cache is outdated because the cache file was produced by a different version
54 List<Type> deserializedTypes = new List<Type>();
55 foreach (XmlNode assemblyNode in rootElement.ChildNodes) {
56 string assemblyName = assemblyNode.Attributes["name"].Value;
57 Assembly assembly = Assembly.Load(assemblyName);
59 foreach (XmlNode moduleNode in assemblyNode.ChildNodes) {
60 Guid moduleVersionId = new Guid(moduleNode.Attributes["versionId"].Value);
62 foreach (XmlNode typeNode in moduleNode.ChildNodes) {
63 string typeName = typeNode.InnerText;
64 Type type = assembly.GetType(typeName);
65 if (type == null || type.Module.ModuleVersionId != moduleVersionId) {
66 // The cache is outdated because we couldn't find a previously recorded
67 // type or the type's containing module was modified.
71 deserializedTypes.Add(type);
77 return deserializedTypes;
80 public void SerializeTypes(IEnumerable<Type> types, TextWriter output) {
81 var groupedByAssembly = from type in types
82 group type by type.Module into groupedByModule
83 group groupedByModule by groupedByModule.Key.Assembly;
85 XmlDocument doc = new XmlDocument();
86 doc.AppendChild(doc.CreateComment(MvcResources.TypeCache_DoNotModify));
88 XmlElement typeCacheElement = doc.CreateElement("typeCache");
89 doc.AppendChild(typeCacheElement);
90 typeCacheElement.SetAttribute("lastModified", CurrentDate.ToString());
91 typeCacheElement.SetAttribute("mvcVersionId", _mvcVersionId.ToString());
93 foreach (var assemblyGroup in groupedByAssembly) {
94 XmlElement assemblyElement = doc.CreateElement("assembly");
95 typeCacheElement.AppendChild(assemblyElement);
96 assemblyElement.SetAttribute("name", assemblyGroup.Key.FullName);
98 foreach (var moduleGroup in assemblyGroup) {
99 XmlElement moduleElement = doc.CreateElement("module");
100 assemblyElement.AppendChild(moduleElement);
101 moduleElement.SetAttribute("versionId", moduleGroup.Key.ModuleVersionId.ToString());
103 foreach (Type type in moduleGroup) {
104 XmlElement typeElement = doc.CreateElement("type");
105 moduleElement.AppendChild(typeElement);
106 typeElement.AppendChild(doc.CreateTextNode(type.FullName));