The Labs \ Source Viewer \ SSCLI \ System \ UnitySerializationHolder

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. using System.Runtime.Remoting;
  16. using System.Runtime.Serialization;
  17. using System.Reflection;
  18. using System.Globalization;
  19. using System.Runtime.Versioning;
  20. using System.Collections.Generic;
  21. namespace System
  22. {
  23.    
  24.     [Serializable()]
  25.     // Holds classes (Empty, Null, Missing) for which we guarantee that there is only ever one instance of.
  26.     internal class UnitySerializationHolder : ISerializable, IObjectReference
  27.     {
  28.         #region Internal Constants
  29.         internal const int EmptyUnity = 1;
  30.         internal const int NullUnity = 2;
  31.         internal const int MissingUnity = 3;
  32.         internal const int RuntimeTypeUnity = 4;
  33.         internal const int ModuleUnity = 5;
  34.         internal const int AssemblyUnity = 6;
  35.         internal const int GenericParameterTypeUnity = 7;
  36.         internal const int PartialInstantiationTypeUnity = 8;
  37.        
  38.         internal const int Pointer = 1;
  39.         internal const int Array = 2;
  40.         internal const int SzArray = 3;
  41.         internal const int ByRef = 4;
  42.         #endregion
  43.        
  44.         #region Internal Static Members
  45.         static internal void GetUnitySerializationInfo(SerializationInfo info, Missing missing)
  46.         {
  47.             info.SetType(typeof(UnitySerializationHolder));
  48.             info.AddValue("UnityType", MissingUnity);
  49.         }
  50.        
  51.         static internal Type AddElementTypes(SerializationInfo info, Type type)
  52.         {
  53.             List<int> elementTypes = new List<int>();
  54.             while (type.HasElementType) {
  55.                 if (type.IsSzArray) {
  56.                     elementTypes.Add(SzArray);
  57.                 }
  58.                 else if (type.IsArray) {
  59.                     elementTypes.Add(type.GetArrayRank());
  60.                     elementTypes.Add(Array);
  61.                 }
  62.                 else if (type.IsPointer) {
  63.                     elementTypes.Add(Pointer);
  64.                 }
  65.                 else if (type.IsByRef) {
  66.                     elementTypes.Add(ByRef);
  67.                 }
  68.                
  69.                 type = type.GetElementType();
  70.             }
  71.            
  72.             info.AddValue("ElementTypes", elementTypes.ToArray(), typeof(int[]));
  73.            
  74.             return type;
  75.         }
  76.        
  77.         internal Type MakeElementTypes(Type type)
  78.         {
  79.             for (int i = m_elementTypes.Length - 1; i >= 0; i--) {
  80.                 if (m_elementTypes[i] == SzArray) {
  81.                     type = type.MakeArrayType();
  82.                 }
  83.                 else if (m_elementTypes[i] == Array) {
  84.                     type = type.MakeArrayType(m_elementTypes[--i]);
  85.                 }
  86.                 else if ((m_elementTypes[i] == Pointer)) {
  87.                     type = type.MakePointerType();
  88.                 }
  89.                 else if ((m_elementTypes[i] == ByRef)) {
  90.                     type = type.MakeByRefType();
  91.                 }
  92.             }
  93.            
  94.             return type;
  95.         }
  96.        
  97.         static internal void GetUnitySerializationInfo(SerializationInfo info, Type type)
  98.         {
  99.             if (type.GetRootElementType().IsGenericParameter) {
  100.                 type = AddElementTypes(info, type);
  101.                 info.SetType(typeof(UnitySerializationHolder));
  102.                 info.AddValue("UnityType", GenericParameterTypeUnity);
  103.                 info.AddValue("GenericParameterPosition", type.GenericParameterPosition);
  104.                 info.AddValue("DeclaringMethod", type.DeclaringMethod, typeof(MethodBase));
  105.                 info.AddValue("DeclaringType", type.DeclaringType, typeof(Type));
  106.                
  107.                 return;
  108.             }
  109.            
  110.             int unityType = RuntimeTypeUnity;
  111.            
  112.             if (!type.IsGenericTypeDefinition && type.ContainsGenericParameters) {
  113.                 // Partial instantiation
  114.                 unityType = PartialInstantiationTypeUnity;
  115.                 type = AddElementTypes(info, type);
  116.                 info.AddValue("GenericArguments", type.GetGenericArguments(), typeof(Type[]));
  117.                 type = type.GetGenericTypeDefinition();
  118.             }
  119.            
  120.             GetUnitySerializationInfo(info, unityType, type.FullName, Assembly.GetAssembly(type));
  121.         }
  122.        
  123.         static internal void GetUnitySerializationInfo(SerializationInfo info, int unityType, string data, Assembly assembly)
  124.         {
  125.             // A helper method that returns the SerializationInfo that a class utilizing
  126.             // UnitySerializationHelper should return from a call to GetObjectData. It contains
  127.             // the unityType (defined above) and any optional data (used only for the reflection
  128.             // types.)
  129.            
  130.             info.SetType(typeof(UnitySerializationHolder));
  131.             info.AddValue("Data", data, typeof(string));
  132.             info.AddValue("UnityType", unityType);
  133.            
  134.             string assemName;
  135.            
  136.             if (assembly == null) {
  137.                 assemName = String.Empty;
  138.             }
  139.             else {
  140.                 assemName = assembly.FullName;
  141.             }
  142.            
  143.             info.AddValue("AssemblyName", assemName);
  144.         }
  145.         #endregion
  146.        
  147.         #region Private Data Members
  148.         private Type[] m_instantiation;
  149.         private int[] m_elementTypes;
  150.         private int m_genericParameterPosition;
  151.         private Type m_declaringType;
  152.         private MethodBase m_declaringMethod;
  153.         private string m_data;
  154.         private string m_assemblyName;
  155.         private int m_unityType;
  156.         #endregion
  157.        
  158.         #region Constructor
  159.         internal UnitySerializationHolder(SerializationInfo info, StreamingContext context)
  160.         {
  161.             if (info == null)
  162.                 throw new ArgumentNullException("info");
  163.            
  164.             m_unityType = info.GetInt32("UnityType");
  165.            
  166.             if (m_unityType == MissingUnity)
  167.                 return;
  168.            
  169.             if (m_unityType == GenericParameterTypeUnity) {
  170.                 m_declaringMethod = info.GetValue("DeclaringMethod", typeof(MethodBase)) as MethodBase;
  171.                 m_declaringType = info.GetValue("DeclaringType", typeof(Type)) as Type;
  172.                 m_genericParameterPosition = info.GetInt32("GenericParameterPosition");
  173.                 m_elementTypes = info.GetValue("ElementTypes", typeof(int[])) as int[];
  174.                
  175.                 return;
  176.             }
  177.            
  178.             if (m_unityType == PartialInstantiationTypeUnity) {
  179.                 m_instantiation = info.GetValue("GenericArguments", typeof(Type[])) as Type[];
  180.                 m_elementTypes = info.GetValue("ElementTypes", typeof(int[])) as int[];
  181.             }
  182.            
  183.             m_data = info.GetString("Data");
  184.             m_assemblyName = info.GetString("AssemblyName");
  185.         }
  186.         #endregion
  187.        
  188.         #region Private Methods
  189.         private void ThrowInsufficientInformation(string field)
  190.         {
  191.             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_InsufficientDeserializationState"), field));
  192.         }
  193.         #endregion
  194.        
  195.         #region ISerializable
  196.         public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
  197.         {
  198.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnitySerHolder"));
  199.         }
  200.         #endregion
  201.        
  202.         #region IObjectReference
  203.         [ResourceExposure(ResourceScope.None)]
  204.         // The Module here was already created and theoretically scoped. There's not enough information to pass this info through to the serializer, and most serialization instances aren't using machine resources.
  205.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  206.         public virtual object GetRealObject(StreamingContext context)
  207.         {
  208.             // GetRealObject uses the data we have in m_data and m_unityType to do a lookup on the correct
  209.             // object to return. We have specific code here to handle the different types which we support.
  210.             // The reflection types (Assembly, Module, and Type) have to be looked up through their static
  211.             // accessors by name.
  212.            
  213.             Assembly assembly;
  214.            
  215.             switch (m_unityType) {
  216.                 case EmptyUnity:
  217.                    
  218.                     {
  219.                         return Empty.Value;
  220.                     }
  221.                     break;
  222.                 case NullUnity:
  223.                    
  224.                    
  225.                     {
  226.                         return DBNull.Value;
  227.                     }
  228.                     break;
  229.                 case MissingUnity:
  230.                    
  231.                    
  232.                     {
  233.                         return Missing.Value;
  234.                     }
  235.                     break;
  236.                 case PartialInstantiationTypeUnity:
  237.                    
  238.                    
  239.                     {
  240.                         m_unityType = RuntimeTypeUnity;
  241.                         Type definition = GetRealObject(context) as Type;
  242.                         m_unityType = PartialInstantiationTypeUnity;
  243.                        
  244.                         if (m_instantiation[0] == null)
  245.                             return null;
  246.                        
  247.                         return MakeElementTypes(definition.MakeGenericType(m_instantiation));
  248.                     }
  249.                     break;
  250.                 case GenericParameterTypeUnity:
  251.                    
  252.                    
  253.                     {
  254.                         if (m_declaringMethod == null && m_declaringType == null)
  255.                             ThrowInsufficientInformation("DeclaringMember");
  256.                        
  257.                         if (m_declaringMethod != null)
  258.                             return m_declaringMethod.GetGenericArguments()[m_genericParameterPosition];
  259.                        
  260.                         return MakeElementTypes(m_declaringType.GetGenericArguments()[m_genericParameterPosition]);
  261.                     }
  262.                     break;
  263.                 case RuntimeTypeUnity:
  264.                    
  265.                    
  266.                     {
  267.                         if (m_data == null || m_data.Length == 0)
  268.                             ThrowInsufficientInformation("Data");
  269.                        
  270.                         if (m_assemblyName == null)
  271.                             ThrowInsufficientInformation("AssemblyName");
  272.                        
  273.                         if (m_assemblyName.Length == 0)
  274.                             return Type.GetType(m_data, true, false);
  275.                        
  276.                         assembly = Assembly.Load(m_assemblyName);
  277.                        
  278.                         Type t = assembly.GetType(m_data, true, false);
  279.                        
  280.                         return t;
  281.                     }
  282.                     break;
  283.                 case ModuleUnity:
  284.                    
  285.                    
  286.                     {
  287.                         if (m_data == null || m_data.Length == 0)
  288.                             ThrowInsufficientInformation("Data");
  289.                        
  290.                         if (m_assemblyName == null)
  291.                             ThrowInsufficientInformation("AssemblyName");
  292.                        
  293.                         assembly = Assembly.Load(m_assemblyName);
  294.                        
  295.                         Module namedModule = assembly.GetModule(m_data);
  296.                        
  297.                         if (namedModule == null)
  298.                             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_UnableToFindModule"), m_data, m_assemblyName));
  299.                        
  300.                         return namedModule;
  301.                     }
  302.                     break;
  303.                 case AssemblyUnity:
  304.                    
  305.                    
  306.                     {
  307.                         if (m_data == null || m_data.Length == 0)
  308.                             ThrowInsufficientInformation("Data");
  309.                        
  310.                         if (m_assemblyName == null)
  311.                             ThrowInsufficientInformation("AssemblyName");
  312.                        
  313.                         assembly = Assembly.Load(m_assemblyName);
  314.                        
  315.                         return assembly;
  316.                     }
  317.                     break;
  318.                 default:
  319.                    
  320.                     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUnity"));
  321.                     break;
  322.             }
  323.         }
  324.         #endregion
  325.     }
  326.    
  327. }

Developer Fusion