2 // System.Runtime.Remoting.RemotingServices.cs
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez Gual (lsg@ctv.es)
8 // (C) 2001 Ximian, Inc. http://www.ximian.com
12 using System.Reflection;
13 using System.Threading;
14 using System.Collections;
15 using System.Runtime.Remoting.Messaging;
16 using System.Runtime.Remoting.Proxies;
17 using System.Runtime.Remoting.Channels;
18 using System.Runtime.Remoting.Contexts;
19 using System.Runtime.CompilerServices;
20 using System.Runtime.Serialization;
22 namespace System.Runtime.Remoting
24 public sealed class RemotingServices
26 // Holds the identities of the objects, using uri as index
27 static Hashtable uri_hash = new Hashtable ();
29 internal static string app_id;
30 static int next_id = 1;
32 static RemotingServices ()
34 app_id = "/" + Guid.NewGuid().ToString().Replace('-', '_') + "/";
37 private RemotingServices () {}
39 [MethodImplAttribute(MethodImplOptions.InternalCall)]
40 internal extern static object InternalExecute (MonoMethod method, Object obj,
41 Object[] parameters, out object [] out_args);
43 [MethodImplAttribute(MethodImplOptions.InternalCall)]
44 public extern static bool IsTransparentProxy (object proxy);
46 internal static IMethodReturnMessage InternalExecuteMessage (
47 MarshalByRefObject target, IMethodCallMessage reqMsg)
51 MonoMethod method = (MonoMethod)reqMsg.MethodBase;
55 object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
56 result = new ReturnMessage (rval, out_args, out_args.Length,
57 reqMsg.LogicalCallContext, reqMsg);
59 } catch (Exception e) {
60 result = new ReturnMessage (e, reqMsg);
66 public static IMethodReturnMessage ExecuteMessage (
67 MarshalByRefObject target, IMethodCallMessage reqMsg)
69 if (IsTransparentProxy(target))
71 // Message must go through all chain of sinks
72 RealProxy rp = GetRealProxy (target);
73 return (IMethodReturnMessage) rp.Invoke (reqMsg);
76 return InternalExecuteMessage (target, reqMsg);
79 public static object Connect (Type classToProxy, string url)
81 return GetRemoteObject(classToProxy, url, null);
84 public static object Connect (Type classToProxy, string url, object data)
86 return GetRemoteObject (classToProxy, url, data);
89 public static Type GetServerTypeForUri (string uri)
91 object svr = GetServerForUri (uri);
96 return svr.GetType ();
99 public static string GetObjectUri (MarshalByRefObject obj)
101 if (IsTransparentProxy(obj))
103 return GetRealProxy (obj).ObjectIdentity.ObjectUri;
106 return obj.ObjectIdentity.ObjectUri;
109 internal static MarshalByRefObject GetServerForUri (string uri)
113 return (MarshalByRefObject)((Identity)uri_hash [uri]).RealObject;
117 internal static Identity GetIdentityForUri (string uri)
121 return (Identity)uri_hash [uri];
125 private static Identity GetClientIdentity(Type requiredType, string url, object channelData)
127 // This method looks for an identity for the given url.
128 // If an identity is not found, it creates the identity and
129 // assigns it a proxy to the remote object.
131 // Creates the client sink chain for the given url or channelData.
132 // It will also get the object uri from the url.
135 IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
138 string msg = String.Format ("Cannot create channel sink to connect to URL {0}.", url);
139 throw new RemotingException (msg);
144 Identity identity = (Identity)uri_hash [objectUri];
145 if (identity != null)
146 return identity; // Object already registered
148 // Creates an identity and a proxy for the remote object
150 identity = new Identity(objectUri, null, requiredType);
151 identity.ClientSink = sink;
153 RemotingProxy proxy = new RemotingProxy (requiredType, identity);
154 identity.RealObject = proxy.GetTransparentProxy();
156 // Registers the identity
157 uri_hash [objectUri] = identity;
162 private static Identity GetServerIdentity(MarshalByRefObject realObject, string objectUri)
164 // This method looks for an identity for the given object.
165 // If an identity is not found, it creates the identity and
166 // assigns it to the given object
170 Identity identity = (Identity)uri_hash [objectUri];
171 if (identity != null)
172 return identity; // Object already registered
174 identity = new Identity (objectUri, Context.DefaultContext, realObject.GetType());
175 identity.RealObject = realObject;
177 // Registers the identity
178 uri_hash[objectUri] = identity;
179 realObject.ObjectIdentity = identity;
185 internal static object GetRemoteObject(Type requiredType, string url, object channelData)
187 Identity id = GetClientIdentity(requiredType, url, channelData);
188 return id.RealObject;
191 public static object Unmarshal (ObjRef objref)
193 return Unmarshal(objref, false);
196 public static object Unmarshal (ObjRef objref, bool fRefine)
198 // FIXME: use type name when fRefine==true
199 Type requiredType = Type.GetType(objref.TypeInfo.TypeName);
200 return GetRemoteObject(requiredType, null, objref.ChannelInfo.ChannelData);
203 public static ObjRef Marshal (MarshalByRefObject obj)
205 return Marshal (obj, null, null);
208 public static ObjRef Marshal (MarshalByRefObject obj, string uri)
210 return Marshal (obj, uri, null);
213 public static ObjRef Marshal (MarshalByRefObject obj, string uri, Type requested_type)
215 if (IsTransparentProxy (obj))
217 RealProxy proxy = RemotingServices.GetRealProxy(obj);
218 if (proxy != null && proxy.ObjectIdentity != null)
221 throw new RemotingException ("It is not possible marshal a proxy of a remote object");
223 return proxy.ObjectIdentity.CreateObjRef(requested_type);
227 if (uri == null) uri = app_id + Environment.TickCount + "_" + next_id++;
229 // It creates the identity if not found
230 Identity identity = GetServerIdentity (obj, uri);
232 if (obj != identity.RealObject)
233 throw new RemotingException ("uri already in use, " + uri);
234 // already registered
236 return identity.CreateObjRef(requested_type);
239 public static RealProxy GetRealProxy (object proxy)
241 if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy");
242 return (RealProxy)((TransparentProxy)proxy)._rp;