RemotingServices.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // System.Runtime.Remoting.RemotingServices.cs
  3. //
  4. // Authors:
  5. // Dietmar Maurer ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // (C) 2001 Ximian, Inc. http://www.ximian.com
  9. //
  10. using System;
  11. using System.Reflection;
  12. using System.Threading;
  13. using System.Collections;
  14. using System.Runtime.Remoting.Messaging;
  15. using System.Runtime.Remoting.Proxies;
  16. using System.Runtime.Remoting.Channels;
  17. using System.Runtime.Remoting.Contexts;
  18. using System.Runtime.CompilerServices;
  19. using System.Runtime.Serialization;
  20. namespace System.Runtime.Remoting
  21. {
  22. public sealed class RemotingServices
  23. {
  24. // Holds the identities of the objects, using uri as index
  25. static Hashtable uri_hash = new Hashtable ();
  26. internal static string app_id;
  27. static int next_id = 1;
  28. static RemotingServices ()
  29. {
  30. app_id = "/" + Guid.NewGuid().ToString().Replace('-', '_') + "/";
  31. }
  32. private RemotingServices () {}
  33. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  34. internal extern static object InternalExecute (MonoMethod method, Object obj,
  35. Object[] parameters, out object [] out_args);
  36. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  37. public extern static bool IsTransparentProxy (object proxy);
  38. internal static IMethodReturnMessage InternalExecuteMessage (
  39. MarshalByRefObject target, IMethodCallMessage reqMsg)
  40. {
  41. ReturnMessage result;
  42. MonoMethod method = (MonoMethod)reqMsg.MethodBase;
  43. try {
  44. object [] out_args;
  45. object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
  46. result = new ReturnMessage (rval, out_args, out_args.Length,
  47. reqMsg.LogicalCallContext, reqMsg);
  48. } catch (Exception e) {
  49. result = new ReturnMessage (e, reqMsg);
  50. }
  51. return result;
  52. }
  53. public static IMethodReturnMessage ExecuteMessage (
  54. MarshalByRefObject target, IMethodCallMessage reqMsg)
  55. {
  56. if (IsTransparentProxy(target))
  57. {
  58. // Message must go through all chain of sinks
  59. RealProxy rp = GetRealProxy (target);
  60. return (IMethodReturnMessage) rp.Invoke (reqMsg);
  61. }
  62. else // Direct call
  63. return InternalExecuteMessage (target, reqMsg);
  64. }
  65. public static object Connect (Type classToProxy, string url)
  66. {
  67. return GetRemoteObject(classToProxy, url, null);
  68. }
  69. public static object Connect (Type classToProxy, string url, object data)
  70. {
  71. return GetRemoteObject (classToProxy, url, data);
  72. }
  73. public static Type GetServerTypeForUri (string uri)
  74. {
  75. object svr = GetServerForUri (uri);
  76. if (svr == null)
  77. return null;
  78. return svr.GetType ();
  79. }
  80. public static string GetObjectUri (MarshalByRefObject obj)
  81. {
  82. if (IsTransparentProxy(obj))
  83. {
  84. return GetRealProxy (obj).ObjectIdentity.ObjectUri;
  85. }
  86. else
  87. return obj.ObjectIdentity.ObjectUri;
  88. }
  89. internal static MarshalByRefObject GetServerForUri (string uri)
  90. {
  91. lock (uri_hash)
  92. {
  93. return (MarshalByRefObject)((Identity)uri_hash [uri]).RealObject;
  94. }
  95. }
  96. internal static Identity GetIdentityForUri (string uri)
  97. {
  98. lock (uri_hash)
  99. {
  100. return (Identity)uri_hash [uri];
  101. }
  102. }
  103. private static Identity GetClientIdentity(Type requiredType, string url, object channelData)
  104. {
  105. // This method looks for an identity for the given url.
  106. // If an identity is not found, it creates the identity and
  107. // assigns it a proxy to the remote object.
  108. // Creates the client sink chain for the given url or channelData.
  109. // It will also get the object uri from the url.
  110. string objectUri;
  111. IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
  112. if (sink == null)
  113. {
  114. string msg = String.Format ("Cannot create channel sink to connect to URL {0}.", url);
  115. throw new RemotingException (msg);
  116. }
  117. lock (uri_hash)
  118. {
  119. Identity identity = (Identity)uri_hash [objectUri];
  120. if (identity != null)
  121. return identity; // Object already registered
  122. // Creates an identity and a proxy for the remote object
  123. identity = new Identity(objectUri, null, requiredType);
  124. identity.ClientSink = sink;
  125. RemotingProxy proxy = new RemotingProxy (requiredType, identity);
  126. identity.RealObject = proxy.GetTransparentProxy();
  127. // Registers the identity
  128. uri_hash [objectUri] = identity;
  129. return identity;
  130. }
  131. }
  132. private static Identity GetServerIdentity(MarshalByRefObject realObject, string objectUri)
  133. {
  134. // This method looks for an identity for the given object.
  135. // If an identity is not found, it creates the identity and
  136. // assigns it to the given object
  137. lock (uri_hash)
  138. {
  139. Identity identity = (Identity)uri_hash [objectUri];
  140. if (identity != null)
  141. return identity; // Object already registered
  142. identity = new Identity (objectUri, Context.DefaultContext, realObject.GetType());
  143. identity.RealObject = realObject;
  144. // Registers the identity
  145. uri_hash[objectUri] = identity;
  146. realObject.ObjectIdentity = identity;
  147. return identity;
  148. }
  149. }
  150. internal static object GetRemoteObject(Type requiredType, string url, object channelData)
  151. {
  152. Identity id = GetClientIdentity(requiredType, url, channelData);
  153. return id.RealObject;
  154. }
  155. public static object Unmarshal (ObjRef objref)
  156. {
  157. return Unmarshal(objref, false);
  158. }
  159. public static object Unmarshal (ObjRef objref, bool fRefine)
  160. {
  161. // FIXME: use type name when fRefine==true
  162. Type requiredType = Type.GetType(objref.TypeInfo.TypeName);
  163. return GetRemoteObject(requiredType, null, objref.ChannelInfo.ChannelData);
  164. }
  165. public static ObjRef Marshal (MarshalByRefObject obj)
  166. {
  167. return Marshal (obj, null, null);
  168. }
  169. public static ObjRef Marshal (MarshalByRefObject obj, string uri)
  170. {
  171. return Marshal (obj, uri, null);
  172. }
  173. public static ObjRef Marshal (MarshalByRefObject obj, string uri, Type requested_type)
  174. {
  175. if (IsTransparentProxy (obj))
  176. {
  177. RealProxy proxy = RemotingServices.GetRealProxy(obj);
  178. if (proxy != null && proxy.ObjectIdentity != null)
  179. {
  180. if (uri != null)
  181. throw new RemotingException ("It is not possible marshal a proxy of a remote object");
  182. return proxy.ObjectIdentity.CreateObjRef(requested_type);
  183. }
  184. }
  185. if (uri == null) uri = app_id + Environment.TickCount + "_" + next_id++;
  186. // It creates the identity if not found
  187. Identity identity = GetServerIdentity (obj, uri);
  188. if (obj != identity.RealObject)
  189. throw new RemotingException ("uri already in use, " + uri);
  190. // already registered
  191. return identity.CreateObjRef(requested_type);
  192. }
  193. public static RealProxy GetRealProxy (object proxy)
  194. {
  195. if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy");
  196. return (RealProxy)((TransparentProxy)proxy)._rp;
  197. }
  198. }
  199. }