2 // System.Runtime.Remoting.Proxies.RealProxy.cs
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez (lsg@ctv.es)
9 // (C) 2001 Ximian, Inc. http://www.ximian.com
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System
.Reflection
;
37 using System
.Runtime
.Remoting
;
38 using System
.Runtime
.Remoting
.Messaging
;
39 using System
.Runtime
.Remoting
.Activation
;
40 using System
.Runtime
.Remoting
.Contexts
;
41 using System
.Runtime
.CompilerServices
;
42 using System
.Runtime
.Serialization
;
45 namespace System
.Runtime
.Remoting
.Proxies
47 internal class TransparentProxy
{
50 bool _custom_type_info
;
53 public abstract class RealProxy
{
56 internal Context _targetContext
;
57 MarshalByRefObject _server
;
58 internal Identity _objectIdentity
;
62 protected RealProxy ()
66 protected RealProxy (Type classToProxy
) : this(classToProxy
, IntPtr
.Zero
, null)
70 internal RealProxy (Type classToProxy
, ClientIdentity identity
) : this(classToProxy
, IntPtr
.Zero
, null)
72 _objectIdentity
= identity
;
75 protected RealProxy (Type classToProxy
, IntPtr stub
, object stubData
)
77 if (!classToProxy
.IsMarshalByRef
&& !classToProxy
.IsInterface
)
78 throw new ArgumentException("object must be MarshalByRef");
80 this.class_to_proxy
= classToProxy
;
82 if (stub
!= IntPtr
.Zero
)
83 throw new NotSupportedException ("stub is not used in Mono");
86 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
87 extern static Type
InternalGetProxyType (object transparentProxy
);
89 public Type
GetProxiedType()
92 if (class_to_proxy
.IsInterface
) return typeof(MarshalByRefObject
);
93 else return class_to_proxy
;
95 return InternalGetProxyType (_objTP
);
98 public virtual ObjRef
CreateObjRef (Type requestedType
)
100 return RemotingServices
.Marshal ((MarshalByRefObject
) GetTransparentProxy(), null, requestedType
);
103 public virtual void GetObjectData (SerializationInfo info
, StreamingContext context
)
105 Object obj
= GetTransparentProxy();
106 RemotingServices
.GetObjectData (obj
, info
, context
);
109 internal Identity ObjectIdentity
111 get { return _objectIdentity; }
112 set { _objectIdentity = value; }
116 public virtual IntPtr
GetCOMIUnknown (bool fIsMarshalled
)
118 throw new NotImplementedException ();
122 public virtual void SetCOMIUnknown (IntPtr i
)
124 throw new NotImplementedException ();
128 public virtual IntPtr
SupportsInterface (ref Guid iid
)
130 throw new NotImplementedException ();
133 public static object GetStubData (RealProxy rp
)
138 public static void SetStubData (RealProxy rp
, object stubData
)
140 rp
._stubData
= stubData
;
143 public abstract IMessage
Invoke (IMessage msg
);
145 /* this is called from unmanaged code */
146 internal static object PrivateInvoke (RealProxy rp
, IMessage msg
, out Exception exc
,
147 out object [] out_args
)
149 MonoMethodMessage mMsg
= (MonoMethodMessage
) msg
;
150 mMsg
.LogicalCallContext
= CallContext
.CreateLogicalCallContext();
151 CallType call_type
= mMsg
.CallType
;
152 bool is_remproxy
= (rp
as RemotingProxy
) != null;
154 IMethodReturnMessage res_msg
= null;
156 if (call_type
== CallType
.BeginInvoke
)
157 // todo: set CallMessage in runtime instead
158 mMsg
.AsyncResult
.CallMessage
= mMsg
;
160 if (call_type
== CallType
.EndInvoke
)
161 res_msg
= (IMethodReturnMessage
)mMsg
.AsyncResult
.EndInvoke ();
163 // Check for constructor msg
164 if (mMsg
.MethodBase
.IsConstructor
)
167 res_msg
= (IMethodReturnMessage
) (rp
as RemotingProxy
).ActivateRemoteObject ((IMethodMessage
) msg
);
169 msg
= new ConstructionCall (rp
.GetProxiedType ());
174 res_msg
= (IMethodReturnMessage
)rp
.Invoke (msg
);
176 // Note, from begining this code used AsyncResult.IsCompleted for
177 // checking if it was a remoting or custom proxy, but in some
178 // cases the remoting proxy finish before the call returns
179 // causing this method to be called, therefore causing all kind of bugs.
180 if ((!is_remproxy
) && call_type
== CallType
.BeginInvoke
)
182 IMessage asyncMsg
= null;
184 // allow calltype EndInvoke to finish
185 asyncMsg
= mMsg
.AsyncResult
.SyncProcessMessage (res_msg
as IMessage
);
186 res_msg
= new ReturnMessage (asyncMsg
, null, 0, null, res_msg
as IMethodCallMessage
);
190 if (res_msg
.LogicalCallContext
!= null && res_msg
.LogicalCallContext
.HasInfo
)
191 CallContext
.UpdateCurrentCallContext (res_msg
.LogicalCallContext
);
193 exc
= res_msg
.Exception
;
195 // todo: remove throw exception from the runtime invoke
198 throw exc
.FixRemotingException();
200 else if (res_msg
is IConstructionReturnMessage
|| mMsg
.CallType
== CallType
.BeginInvoke
) {
201 out_args
= res_msg
.OutArgs
;
203 else if (mMsg
.CallType
== CallType
.Sync
) {
204 out_args
= ProcessResponse (res_msg
, mMsg
);
206 else if (mMsg
.CallType
== CallType
.EndInvoke
) {
207 out_args
= ProcessResponse (res_msg
, mMsg
.AsyncResult
.CallMessage
);
210 out_args
= res_msg
.OutArgs
;
213 return res_msg
.ReturnValue
;
216 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
217 internal extern virtual object InternalGetTransparentProxy (string className
);
219 public virtual object GetTransparentProxy ()
224 IRemotingTypeInfo rti
= this as IRemotingTypeInfo
;
228 if (name
== null || name
== typeof(MarshalByRefObject
).AssemblyQualifiedName
)
229 name
= class_to_proxy
.AssemblyQualifiedName
;
232 name
= class_to_proxy
.AssemblyQualifiedName
;
234 _objTP
= InternalGetTransparentProxy (name
);
240 public IConstructionReturnMessage
InitializeServerObject(IConstructionCallMessage ctorMsg
)
242 throw new NotImplementedException();
245 protected void AttachServer(MarshalByRefObject s
)
250 protected MarshalByRefObject
DetachServer()
252 MarshalByRefObject ob
= _server
;
257 protected MarshalByRefObject
GetUnwrappedServer()
262 static object[] ProcessResponse (IMethodReturnMessage mrm
, IMethodCallMessage call
)
266 MethodInfo mi
= (MethodInfo
) call
.MethodBase
;
267 if (mrm
.ReturnValue
!= null && !mi
.ReturnType
.IsInstanceOfType (mrm
.ReturnValue
))
268 throw new RemotingException ("Return value has an invalid type");
270 // Check out parameters
272 if (mrm
.OutArgCount
> 0)
274 ParameterInfo
[] parameters
= mi
.GetParameters();
276 foreach (ParameterInfo par
in parameters
)
277 if (par
.ParameterType
.IsByRef
) no
++;
279 object[] outArgs
= new object [no
];
283 foreach (ParameterInfo par
in parameters
)
285 if (par
.IsOut
&& !par
.ParameterType
.IsByRef
)
287 // Special marshalling required
289 object outArg
= mrm
.GetOutArg (nout
++);
290 if (outArg
!= null) {
291 object local
= call
.GetArg (par
.Position
);
292 if (local
== null) throw new RemotingException ("Unexpected null value in local out parameter '" + par
.Position
+ " " + par
.Name
+ "'");
293 RemotingServices
.UpdateOutArgObject (par
, local
, outArg
);
296 else if (par
.ParameterType
.IsByRef
)
298 object outArg
= mrm
.GetOutArg (nout
++);
299 if (outArg
!= null && !par
.ParameterType
.IsInstanceOfType (outArg
))
301 throw new RemotingException ("Return argument '" + par
.Name
+ "' has an invalid type");
303 outArgs
[narg
++] = outArg
;
309 return new object [0];