File: objectclonehelper.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (180 lines) | stat: -rw-r--r-- 7,413 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// ==++==
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
/*============================================================
 **
 ** Class: ObjectCloneHelper
 **
 **
 ** Purpose: Helper methods used by ObjectClone to process ISerializable objects etc
 **
 **
 ===========================================================*/
#if FEATURE_REMOTING

namespace System.Runtime.Serialization
{
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Proxies;
    using System.Runtime.Remoting.Messaging;
    using System.Runtime.Serialization;
    using System;
    using System.Collections;
    using System.Reflection;
    using System.Diagnostics;
    using System.Globalization;

    internal static class ObjectCloneHelper
    {
        static readonly IFormatterConverter s_converter = new FormatterConverter();
        // Currently object cloner is used only to clone stuff across domains. If its used to clone objects within a domain
        // the Clone context will need to be created too..
        static readonly StreamingContext    s_cloneContext = new StreamingContext(StreamingContextStates.CrossAppDomain);
        static readonly ISerializationSurrogate  s_RemotingSurrogate = new RemotingSurrogate();
        static readonly ISerializationSurrogate  s_ObjRefRemotingSurrogate = new ObjRefSurrogate();
        
        [System.Security.SecurityCritical]  // auto-generated
        internal static object GetObjectData(object serObj, out string typeName, out string assemName, out string[] fieldNames, out object[] fieldValues)
        {
            Type objectType = null;
            object retObj = null;
            
            if (RemotingServices.IsTransparentProxy(serObj))
                objectType = typeof(MarshalByRefObject);
            else
                objectType = serObj.GetType();
                
            SerializationInfo  si  = new SerializationInfo(objectType, s_converter);
            if (serObj is ObjRef)
            {
                s_ObjRefRemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
            }
            else if (RemotingServices.IsTransparentProxy(serObj) || serObj is MarshalByRefObject)
            {
#if !MONO
                // We can only try to smuggle objref's for actual CLR objects
                //   or for RemotingProxy's.
                if (!RemotingServices.IsTransparentProxy(serObj) ||
                    RemotingServices.GetRealProxy(serObj) is RemotingProxy)
                {                
                    ObjRef objRef = RemotingServices.MarshalInternal((MarshalByRefObject)serObj, null, null);
                    if (objRef.CanSmuggle())
                    {
                        if (RemotingServices.IsTransparentProxy(serObj))
                        {
                            RealProxy rp = RemotingServices.GetRealProxy(serObj);
                            objRef.SetServerIdentity(rp._srvIdentity);
                            objRef.SetDomainID(rp._domainID);
                        }
                        else
                        {
                            ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity((MarshalByRefObject)serObj);
                            srvId.SetHandle();
                            objRef.SetServerIdentity(srvId.GetHandle());
                            objRef.SetDomainID(AppDomain.CurrentDomain.GetId());
                        }
                        objRef.SetMarshaledObject();
                        retObj = objRef;
                    }
                }
#endif
                if (retObj == null)
                {
                    // Deal with the non-smugglable remoting objects
                    s_RemotingSurrogate.GetObjectData(serObj, si, s_cloneContext);
                }
                
            }
            else if (serObj is ISerializable)
            {
                ((ISerializable)serObj).GetObjectData(si, s_cloneContext);
            }
            else
            {
                // Getting here means a bug in cloner
                throw new ArgumentException(Environment.GetResourceString("Arg_SerializationException"));
            }

            if (retObj == null)
            {
                typeName = si.FullTypeName;
                assemName = si.AssemblyName;
                fieldNames = si.MemberNames;
                fieldValues = si.MemberValues;
            }
            else
            {
                typeName = null;
                assemName = null;
                fieldNames = null;
                fieldValues = null;
            }

            return retObj;
        }

        [System.Security.SecurityCritical]  // auto-generated
        internal static SerializationInfo PrepareConstructorArgs(object serObj, string[] fieldNames, object[] fieldValues, out StreamingContext context)
        {
            SerializationInfo si = null;
            if (serObj is ISerializable)
            {
                si = new SerializationInfo(serObj.GetType(), s_converter);

                for (int i =0; i < fieldNames.Length; i++)
                {
                    if (fieldNames[i] != null)
                        si.AddValue(fieldNames[i], fieldValues[i]);
                }
            }
            else
            {
                // We have a case where the from object was ISerializable and to object is not
                // @

                Hashtable fields = new Hashtable();
                int incomingFieldIndex = 0;
                int numIncomingFields = 0;
                for (; incomingFieldIndex < fieldNames.Length; incomingFieldIndex++)
                {
                    if (fieldNames[incomingFieldIndex] != null)
                    {
                        fields[fieldNames[incomingFieldIndex]] = fieldValues[incomingFieldIndex];
                        numIncomingFields++;
                    }
                }
                
                MemberInfo[] mi = FormatterServices.GetSerializableMembers(serObj.GetType());

                for (int index = 0; index < mi.Length; index++)
                {
                    string fieldName = mi[index].Name;
                    if (!fields.Contains(fieldName))
                    {
                        // If we are missing a field value then it's not necessarily
                        // the end of the world: check whether the field is marked
                        // [OptionalField].
                        Object [] attrs = mi[index].GetCustomAttributes(typeof(OptionalFieldAttribute), false);
                        if (attrs == null || attrs.Length == 0)
                            throw new SerializationException(Environment.GetResourceString("Serialization_MissingMember",
                                                                           mi[index],
                                                                           serObj.GetType(),
                                                                           typeof(OptionalFieldAttribute).FullName));
                        continue;
                    }

                    object value = fields[fieldName];

                    FormatterServices.SerializationSetValue(mi[index], serObj, value);
                }
            }

            context = s_cloneContext;
            return si;
        }
    }

}
#endif // FEATURE_REMOTING