Bump corefx
[mono.git] / mcs / class / referencesource / mscorlib / system / marshalbyrefobject.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** File:    MarshalByRefObject.cs
9 **
10 **              
11 **
12 ** Purpose: Defines the root type for all marshal by reference aka
13 **          AppDomain bound types
14 **          
15 **
16 **
17 ===========================================================*/
18 namespace System {
19     
20     using System;
21     using System.Security;
22     using System.Security.Permissions;
23     using System.Threading;
24     using System.Runtime.Remoting;
25 #if FEATURE_REMOTING    
26     using System.Runtime.Remoting.Lifetime;
27     using System.Runtime.Remoting.Services;
28 #endif
29     using System.Runtime.InteropServices;
30     using System.Reflection;
31     using System.Runtime.CompilerServices;
32     using System.Runtime.Versioning;
33     using System.Diagnostics.Contracts;
34     using CultureInfo = System.Globalization.CultureInfo;
35
36     [Serializable]
37 [System.Runtime.InteropServices.ComVisible(true)]
38     public abstract class MarshalByRefObject 
39     {
40 #if FEATURE_REMOTING    
41         private Object __identity;        
42
43         private Object Identity { get { return __identity; } set { __identity = value; } }        
44 #if FEATURE_COMINTEROP
45         [System.Security.SecuritySafeCritical]  // auto-generated
46         internal IntPtr GetComIUnknown(bool fIsBeingMarshalled)
47         {
48             IntPtr pUnk;
49             if(RemotingServices.IsTransparentProxy(this))
50             {
51                 pUnk = RemotingServices.GetRealProxy(this).GetCOMIUnknown(fIsBeingMarshalled);
52             }
53             else
54             {
55                 pUnk = Marshal.GetIUnknownForObject(this);
56             }
57             return pUnk;
58         }
59
60         [System.Security.SecurityCritical]  // auto-generated
61         [MethodImplAttribute(MethodImplOptions.InternalCall)]
62         [ResourceExposure(ResourceScope.None)]
63         internal static extern IntPtr GetComIUnknown(MarshalByRefObject o);
64 #endif // FEATURE_COMINTEROP
65
66         // (1) for remote COM objects IsInstance of can't be executed on
67         // the proxies, so we need this method to be executed on the 
68         // actual object.
69         // (2) for remote objects that do not have the complete type information
70         // we intercept calls to check the type and execute it on the actual
71         // object
72         internal bool IsInstanceOfType(Type T)
73         {
74             return T.IsInstanceOfType(this);
75         }
76
77         // for remote COM Objects the late binding methods can't be
78         // executed on proxies, so we need this method to execute on
79         // the real object
80         internal Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, 
81                             Object[] args,ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters)
82         {
83             Type t = GetType();
84             
85             // Sanity check
86             if(!t.IsCOMObject)
87                 throw new InvalidOperationException(Environment.GetResourceString("Arg_InvokeMember"));
88
89             // Call into the runtime to invoke on the COM object.
90             return t.InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters);
91         }
92
93         // Returns a new cloned MBR instance that is a memberwise copy of this 
94         // with the identity nulled out, so there are no identity conflicts
95         // when the cloned object is marshalled
96         protected MarshalByRefObject MemberwiseClone(bool cloneIdentity)
97         {
98             MarshalByRefObject mbr = (MarshalByRefObject)base.MemberwiseClone();
99             // set the identity on the cloned object to null
100             if (!cloneIdentity)
101                 mbr.Identity = null;
102             return mbr;
103         }
104
105
106         
107         // A helper routine to extract the identity either from the marshalbyrefobject base
108         // class if it is not a proxy, otherwise from the real proxy.
109         // A flag is set to indicate whether the object passed in is a server or a proxy
110         [System.Security.SecuritySafeCritical]  // auto-generated
111         internal static Identity GetIdentity(MarshalByRefObject obj, out bool fServer)
112         {
113             fServer = true;
114             Identity id = null;
115
116             if(null != obj)
117             {
118                 if(!RemotingServices.IsTransparentProxy(obj))
119                 {
120                     id = (Identity)obj.Identity;
121                 }
122                 else
123                 {                    
124                     // Toggle flag to indicate that we have a proxy
125                     fServer = false;
126                     id = RemotingServices.GetRealProxy(obj).IdentityObject;
127                 }
128             }
129
130             return id;
131         }
132
133         // Another helper that delegates to the helper above
134         internal static Identity GetIdentity(MarshalByRefObject obj)
135         {
136             Contract.Assert(!RemotingServices.IsTransparentProxy(obj), "Use this method for server objects only");
137
138             bool fServer;            
139             return GetIdentity(obj, out fServer);
140         }
141
142        
143         internal ServerIdentity __RaceSetServerIdentity(ServerIdentity id)
144         {
145             if (__identity == null)
146             {
147                 // For strictly MBR types, the TP field in the identity
148                 // holds the real server
149                 if (!id.IsContextBound)
150                 {
151                     id.RaceSetTransparentProxy(this);
152                 }
153                 Interlocked.CompareExchange(ref __identity, id, null);
154             }
155             return (ServerIdentity)__identity;
156         }
157
158
159         internal void __ResetServerIdentity()
160         {
161             __identity = null;
162         }
163         
164        // This method is used return a lifetime service object which
165        // is used to control the lifetime policy to the object.
166        // For the default Lifetime service this will be an object of typoe ILease.
167        // 
168         [System.Security.SecurityCritical]  // auto-generated_required
169         public Object GetLifetimeService()
170         {
171             return LifetimeServices.GetLease(this); 
172         }
173
174        // This method is used return lifetime service object. This method
175        // can be overridden to return a LifetimeService object with properties unique to
176        // this object.
177        // For the default Lifetime service this will be an object of type ILease.
178        // 
179         [System.Security.SecurityCritical]  // auto-generated_required
180         public virtual Object InitializeLifetimeService()
181         {
182             return LifetimeServices.GetLeaseInitial(this);
183         }
184
185         [System.Security.SecurityCritical]  // auto-generated_required
186         public virtual ObjRef CreateObjRef(Type requestedType)
187         {
188             if(__identity == null)
189             {
190                 throw new RemotingException(Environment.GetResourceString(
191                     "Remoting_NoIdentityEntry"));
192             }            
193             return new ObjRef(this, requestedType);
194         }
195
196         // This is for casting interop ObjRefLite's.
197         // ObjRefLite's have been deprecated. These methods are not exposed 
198         // through any user APIs and would be removed in the future
199         [System.Security.SecuritySafeCritical]  // auto-generated
200         internal bool CanCastToXmlType(String xmlTypeName, String xmlTypeNamespace)
201         {
202             Type castType = SoapServices.GetInteropTypeFromXmlType(xmlTypeName, xmlTypeNamespace);
203             if (castType == null)
204             {
205                 String typeNamespace;
206                 String assemblyName;
207                 if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(xmlTypeNamespace, 
208                         out typeNamespace, out assemblyName))
209                     return false;
210
211                 String typeName;
212                 if ((typeNamespace != null) && (typeNamespace.Length > 0))
213                     typeName = typeNamespace + "." + xmlTypeName;
214                 else
215                     typeName = xmlTypeName;
216
217                 try
218                 {
219                     Assembly asm = Assembly.Load(assemblyName);
220                     castType = asm.GetType(typeName, false, false);
221                 }
222                 catch 
223                 {
224                     return false;
225                 }
226             }
227
228             if (castType != null)
229                 return castType.IsAssignableFrom(this.GetType());
230
231             return false;
232         } // CanCastToXmlType
233
234         // helper method for calling CanCastToXmlType
235         // ObjRefLite's have been deprecated. These methods are not exposed 
236         // through any user APIs and would be removed in the future
237         [System.Security.SecuritySafeCritical]  // auto-generated
238         internal static bool CanCastToXmlTypeHelper(RuntimeType castType, MarshalByRefObject o)
239         {
240             if (castType == null)
241                 throw new ArgumentNullException("castType");
242         
243             Contract.EndContractBlock();
244             // MarshalByRefObject's can only be casted to MarshalByRefObject's or interfaces.
245             if (!castType.IsInterface && !castType.IsMarshalByRef)
246                 return false;
247
248             // figure out xml type name
249             String xmlTypeName = null;
250             String xmlTypeNamespace = null;
251             if (!SoapServices.GetXmlTypeForInteropType(castType, out xmlTypeName, out xmlTypeNamespace))
252             {
253                 // There's no registered interop type name, so just use the default.
254                 xmlTypeName = castType.Name;
255                 xmlTypeNamespace =
256                     SoapServices.CodeXmlNamespaceForClrTypeNamespace(
257                         castType.Namespace, castType.GetRuntimeAssembly().GetSimpleName());
258             }
259
260             return o.CanCastToXmlType(xmlTypeName, xmlTypeNamespace);
261         } // CanCastToXmlType
262
263 #endif // FEATURE_REMOTING
264     }            
265 } // namespace