The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization \ ObjectCloneHelper

  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. /*============================================================
  16. **
  17. ** Class: ObjectCloneHelper
  18. **
  19. **
  20. ** Purpose: Helper methods used by ObjectClone to process ISerializable objects etc
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Runtime.Serialization
  25. {
  26.     using System.Runtime.Remoting;
  27.     using System.Runtime.Remoting.Proxies;
  28.     using System.Runtime.Remoting.Messaging;
  29.     using System.Runtime.Serialization;
  30.     using System;
  31.     using System.Collections;
  32.     using System.Reflection;
  33.     using System.Diagnostics;
  34.     using System.Globalization;
  35.    
  36.     internal sealed class ObjectCloneHelper
  37.     {
  38.        
  39.         static IFormatterConverter s_converter = new FormatterConverter();
  40.         // Currently object cloner is used only to clone stuff across domains. If its used to clone objects within a domain
  41.         // the Clone context will need to be created too..
  42.         static StreamingContext s_cloneContext = new StreamingContext(StreamingContextStates.CrossAppDomain);
  43.         static ISerializationSurrogate s_RemotingSurrogate = new RemotingSurrogate();
  44.         static ISerializationSurrogate s_ObjRefRemotingSurrogate = new ObjRefSurrogate();
  45.        
  46.         static internal object GetObjectData(object serObj, out string typeName, out string assemName, out string[] fieldNames, out object[] fieldValues)
  47.         {
  48.             Type objectType = null;
  49.             object retObj = null;
  50.            
  51.             if (RemotingServices.IsTransparentProxy(serObj))
  52.                 objectType = typeof(MarshalByRefObject);
  53.             else
  54.                 objectType = serObj.GetType();
  55.            
  56.             SerializationInfo si = new SerializationInfo(objectType, s_converter);
  57.             if (serObj is ObjRef) {
  58.                 s_ObjRefRemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
  59.             }
  60.             else if (RemotingServices.IsTransparentProxy(serObj) || serObj is MarshalByRefObject) {
  61.                 // We can only try to smuggle objref's for actual CLR objects
  62.                 // or for RemotingProxy's.
  63.                 if (!RemotingServices.IsTransparentProxy(serObj) || RemotingServices.GetRealProxy(serObj) is RemotingProxy) {
  64.                     ObjRef objRef = RemotingServices.MarshalInternal((MarshalByRefObject)serObj, null, null);
  65.                     if (objRef.CanSmuggle()) {
  66.                         if (RemotingServices.IsTransparentProxy(serObj)) {
  67.                             RealProxy rp = RemotingServices.GetRealProxy(serObj);
  68.                             objRef.SetServerIdentity(rp._srvIdentity);
  69.                             objRef.SetDomainID(rp._domainID);
  70.                         }
  71.                         else {
  72.                             ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity((MarshalByRefObject)serObj);
  73.                             srvId.SetHandle();
  74.                             objRef.SetServerIdentity(srvId.GetHandle());
  75.                             objRef.SetDomainID(AppDomain.CurrentDomain.GetId());
  76.                         }
  77.                         objRef.SetMarshaledObject();
  78.                         retObj = objRef;
  79.                     }
  80.                 }
  81.                
  82.                 if (retObj == null) {
  83.                     // Deal with the non-smugglable remoting objects
  84.                     s_RemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
  85.                 }
  86.                
  87.             }
  88.             else if (serObj is ISerializable) {
  89.                 ((ISerializable)serObj).GetObjectData(si, s_cloneContext);
  90.             }
  91.             else {
  92.                 // Getting here means a bug in cloner
  93.                 throw new ArgumentException(Environment.GetResourceString("Arg_SerializationException"));
  94.             }
  95.            
  96.             if (retObj == null) {
  97.                 typeName = si.FullTypeName;
  98.                 assemName = si.AssemblyName;
  99.                 fieldNames = si.MemberNames;
  100.                 fieldValues = si.MemberValues;
  101.             }
  102.             else {
  103.                 typeName = null;
  104.                 assemName = null;
  105.                 fieldNames = null;
  106.                 fieldValues = null;
  107.             }
  108.            
  109.             return retObj;
  110.         }
  111.        
  112.         static internal SerializationInfo PrepareConstructorArgs(object serObj, string[] fieldNames, object[] fieldValues, out StreamingContext context)
  113.         {
  114.             SerializationInfo si = null;
  115.             if (serObj is ISerializable) {
  116.                 si = new SerializationInfo(serObj.GetType(), s_converter);
  117.                
  118.                 for (int i = 0; i < fieldNames.Length; i++) {
  119.                     if (fieldNames[i] != null)
  120.                         si.AddValue(fieldNames[i], fieldValues[i]);
  121.                 }
  122.             }
  123.             else {
  124.                 Hashtable fields = new Hashtable();
  125.                 int incomingFieldIndex = 0;
  126.                 int numIncomingFields = 0;
  127.                 for (; incomingFieldIndex < fieldNames.Length; incomingFieldIndex++) {
  128.                     if (fieldNames[incomingFieldIndex] != null) {
  129.                         fields[fieldNames[incomingFieldIndex]] = fieldValues[incomingFieldIndex];
  130.                         numIncomingFields++;
  131.                     }
  132.                 }
  133.                
  134.                 MemberInfo[] mi = FormatterServices.GetSerializableMembers(serObj.GetType());
  135.                
  136.                 for (int index = 0; index < mi.Length; index++) {
  137.                     string fieldName = mi[index].Name;
  138.                     if (!fields.Contains(fieldName)) {
  139.                         // If we are missing a field value then it's not necessarily
  140.                         // the end of the world: check whether the field is marked
  141.                         // [OptionalField].
  142.                         object[] attrs = mi[index].GetCustomAttributes(typeof(OptionalFieldAttribute), false);
  143.                         if (attrs == null || attrs.Length == 0)
  144.                             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_MissingMember"), mi[index], serObj.GetType(), typeof(OptionalFieldAttribute).FullName));
  145.                         continue;
  146.                     }
  147.                    
  148.                     object value = fields[fieldName];
  149.                    
  150.                     FormatterServices.SerializationSetValue(mi[index], serObj, value);
  151.                 }
  152.             }
  153.            
  154.             context = s_cloneContext;
  155.             return si;
  156.         }
  157.     }
  158.    
  159. }

Developer Fusion