3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** Class: ObjectCloneHelper
11 ** Purpose: Helper methods used by ObjectClone to process ISerializable objects etc
14 ===========================================================*/
17 namespace System.Runtime.Serialization
19 using System.Runtime.Remoting;
20 using System.Runtime.Remoting.Proxies;
21 using System.Runtime.Remoting.Messaging;
22 using System.Runtime.Serialization;
24 using System.Collections;
25 using System.Reflection;
26 using System.Diagnostics;
27 using System.Globalization;
29 internal static class ObjectCloneHelper
31 static readonly IFormatterConverter s_converter = new FormatterConverter();
32 // Currently object cloner is used only to clone stuff across domains. If its used to clone objects within a domain
33 // the Clone context will need to be created too..
34 static readonly StreamingContext s_cloneContext = new StreamingContext(StreamingContextStates.CrossAppDomain);
35 static readonly ISerializationSurrogate s_RemotingSurrogate = new RemotingSurrogate();
36 static readonly ISerializationSurrogate s_ObjRefRemotingSurrogate = new ObjRefSurrogate();
38 [System.Security.SecurityCritical] // auto-generated
39 internal static object GetObjectData(object serObj, out string typeName, out string assemName, out string[] fieldNames, out object[] fieldValues)
41 Type objectType = null;
44 if (RemotingServices.IsTransparentProxy(serObj))
45 objectType = typeof(MarshalByRefObject);
47 objectType = serObj.GetType();
49 SerializationInfo si = new SerializationInfo(objectType, s_converter);
52 s_ObjRefRemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
54 else if (RemotingServices.IsTransparentProxy(serObj) || serObj is MarshalByRefObject)
57 // We can only try to smuggle objref's for actual CLR objects
58 // or for RemotingProxy's.
59 if (!RemotingServices.IsTransparentProxy(serObj) ||
60 RemotingServices.GetRealProxy(serObj) is RemotingProxy)
62 ObjRef objRef = RemotingServices.MarshalInternal((MarshalByRefObject)serObj, null, null);
63 if (objRef.CanSmuggle())
65 if (RemotingServices.IsTransparentProxy(serObj))
67 RealProxy rp = RemotingServices.GetRealProxy(serObj);
68 objRef.SetServerIdentity(rp._srvIdentity);
69 objRef.SetDomainID(rp._domainID);
73 ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity((MarshalByRefObject)serObj);
75 objRef.SetServerIdentity(srvId.GetHandle());
76 objRef.SetDomainID(AppDomain.CurrentDomain.GetId());
78 objRef.SetMarshaledObject();
85 // Deal with the non-smugglable remoting objects
86 s_RemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
90 else if (serObj is ISerializable)
92 ((ISerializable)serObj).GetObjectData(si, s_cloneContext);
96 // Getting here means a bug in cloner
97 throw new ArgumentException(Environment.GetResourceString("Arg_SerializationException"));
102 typeName = si.FullTypeName;
103 assemName = si.AssemblyName;
104 fieldNames = si.MemberNames;
105 fieldValues = si.MemberValues;
118 [System.Security.SecurityCritical] // auto-generated
119 internal static SerializationInfo PrepareConstructorArgs(object serObj, string[] fieldNames, object[] fieldValues, out StreamingContext context)
121 SerializationInfo si = null;
122 if (serObj is ISerializable)
124 si = new SerializationInfo(serObj.GetType(), s_converter);
126 for (int i =0; i < fieldNames.Length; i++)
128 if (fieldNames[i] != null)
129 si.AddValue(fieldNames[i], fieldValues[i]);
134 // We have a case where the from object was ISerializable and to object is not
137 Hashtable fields = new Hashtable();
138 int incomingFieldIndex = 0;
139 int numIncomingFields = 0;
140 for (; incomingFieldIndex < fieldNames.Length; incomingFieldIndex++)
142 if (fieldNames[incomingFieldIndex] != null)
144 fields[fieldNames[incomingFieldIndex]] = fieldValues[incomingFieldIndex];
149 MemberInfo[] mi = FormatterServices.GetSerializableMembers(serObj.GetType());
151 for (int index = 0; index < mi.Length; index++)
153 string fieldName = mi[index].Name;
154 if (!fields.Contains(fieldName))
156 // If we are missing a field value then it's not necessarily
157 // the end of the world: check whether the field is marked
159 Object [] attrs = mi[index].GetCustomAttributes(typeof(OptionalFieldAttribute), false);
160 if (attrs == null || attrs.Length == 0)
161 throw new SerializationException(Environment.GetResourceString("Serialization_MissingMember",
164 typeof(OptionalFieldAttribute).FullName));
168 object value = fields[fieldName];
170 FormatterServices.SerializationSetValue(mi[index], serObj, value);
174 context = s_cloneContext;
180 #endif // FEATURE_REMOTING