2 // System.Runtime.Remoting.RemotingServices.cs
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez Gual (lluis@ideary.com)
9 // (C) 2001 Ximian, Inc. http://www.ximian.com
13 using System.Reflection;
14 using System.Threading;
15 using System.Collections;
16 using System.Runtime.Remoting.Messaging;
17 using System.Runtime.Remoting.Proxies;
18 using System.Runtime.Remoting.Channels;
19 using System.Runtime.Remoting.Contexts;
20 using System.Runtime.Remoting.Activation;
21 using System.Runtime.Remoting.Lifetime;
22 using System.Runtime.CompilerServices;
23 using System.Runtime.Serialization;
25 namespace System.Runtime.Remoting
27 public sealed class RemotingServices
29 // Holds the identities of the objects, using uri as index
30 static Hashtable uri_hash = new Hashtable ();
32 internal static string app_id;
33 static int next_id = 1;
35 static RemotingServices ()
37 app_id = "/" + Guid.NewGuid().ToString().Replace('-', '_') + "/";
39 CreateWellKnownServerIdentity (typeof(RemoteActivator), "RemoteActivationService.rem", WellKnownObjectMode.Singleton);
42 private RemotingServices () {}
44 [MethodImplAttribute(MethodImplOptions.InternalCall)]
45 internal extern static object InternalExecute (MonoMethod method, Object obj,
46 Object[] parameters, out object [] out_args);
48 [MethodImplAttribute(MethodImplOptions.InternalCall)]
49 public extern static bool IsTransparentProxy (object proxy);
51 internal static IMethodReturnMessage InternalExecuteMessage (
52 MarshalByRefObject target, IMethodCallMessage reqMsg)
56 MonoMethod method = (MonoMethod)reqMsg.MethodBase;
60 object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
61 result = new ReturnMessage (rval, out_args, out_args.Length,
62 reqMsg.LogicalCallContext, reqMsg);
64 } catch (Exception e) {
65 result = new ReturnMessage (e, reqMsg);
71 public static IMethodReturnMessage ExecuteMessage (
72 MarshalByRefObject target, IMethodCallMessage reqMsg)
74 if (IsTransparentProxy(target))
76 // Message must go through all chain of sinks
77 RealProxy rp = GetRealProxy (target);
78 return (IMethodReturnMessage) rp.Invoke (reqMsg);
81 return InternalExecuteMessage (target, reqMsg);
84 public static object Connect (Type classToProxy, string url)
86 return GetRemoteObject(classToProxy, url, null, null);
89 public static object Connect (Type classToProxy, string url, object data)
91 return GetRemoteObject (classToProxy, url, data, null);
94 public static Type GetServerTypeForUri (string uri)
96 Identity ident = GetIdentityForUri (uri);
97 if (ident == null) return null;
98 return ident.ObjectType;
101 public static string GetObjectUri (MarshalByRefObject obj)
103 Identity ident = GetObjectIdentity(obj);
104 if (ident != null) return ident.ObjectUri;
108 public static object Unmarshal (ObjRef objref)
110 return Unmarshal(objref, false);
113 public static object Unmarshal (ObjRef objref, bool fRefine)
115 // FIXME: use type name when fRefine==true
116 Type requiredType = Type.GetType(objref.TypeInfo.TypeName);
117 return GetRemoteObject(requiredType, null, objref.ChannelInfo.ChannelData, objref.URI);
120 public static ObjRef Marshal (MarshalByRefObject obj)
122 return Marshal (obj, null, null);
125 public static ObjRef Marshal (MarshalByRefObject obj, string uri)
127 return Marshal (obj, uri, null);
130 public static ObjRef Marshal (MarshalByRefObject obj, string uri, Type requested_type)
132 if (IsTransparentProxy (obj))
134 RealProxy proxy = RemotingServices.GetRealProxy(obj);
135 if (proxy != null && proxy.ObjectIdentity != null)
138 throw new RemotingException ("It is not possible marshal a proxy of a remote object");
140 return proxy.ObjectIdentity.CreateObjRef(requested_type);
144 if (requested_type == null) requested_type = obj.GetType();
148 uri = app_id + Environment.TickCount + "_" + next_id++;
149 CreateClientActivatedServerIdentity (obj, requested_type, uri);
153 ClientActivatedIdentity identity = uri_hash [uri] as ClientActivatedIdentity;
154 if (identity == null || obj != identity.GetServerObject())
\r
155 CreateClientActivatedServerIdentity (obj, requested_type, uri);
158 return obj.CreateObjRef(requested_type);
161 public static RealProxy GetRealProxy (object proxy)
163 if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy");
164 return (RealProxy)((TransparentProxy)proxy)._rp;
167 public static MethodBase GetMethodBaseFromMethodMessage(IMethodMessage msg)
169 Type type = Type.GetType (msg.TypeName);
171 throw new RemotingException ("Type '" + msg.TypeName + "' not found!");
173 BindingFlags bflags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
174 if (msg.MethodSignature == null)
175 return type.GetMethod (msg.MethodName, bflags);
177 return type.GetMethod (msg.MethodName, bflags, null, (Type[]) msg.MethodSignature, null);
180 public static void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
182 if (obj == null) throw new ArgumentNullException ("obj");
184 MarshalByRefObject mbr = (MarshalByRefObject)obj;
187 Identity ident = GetObjectIdentity(mbr);
190 oref = mbr.CreateObjRef(null);
192 oref = Marshal (mbr);
194 oref.GetObjectData (info, context);
197 public static ObjRef GetObjRefForProxy(MarshalByRefObject obj)
199 Identity ident = GetObjectIdentity(obj);
200 if (ident == null) return null;
201 else return ident.CreateObjRef(null);
205 public static string GetSessionIdForMethodMessage(IMethodMessage msg)
207 throw new NotImplementedException ();
210 public static bool IsMethodOverloaded(IMethodMessage msg)
212 Type type = msg.MethodBase.DeclaringType;
213 MemberInfo[] members = type.GetMember (msg.MethodName, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
\r
214 return members.Length > 1;
\r
217 public static bool IsObjectOutOfAppDomain(object tp)
219 Identity ident = GetObjectIdentity((MarshalByRefObject)tp);
220 if (ident != null) return !ident.IsFromThisAppDomain;
224 public static bool IsObjectOutOfContext(object tp)
226 ServerIdentity ident = GetObjectIdentity((MarshalByRefObject)tp) as ServerIdentity;
227 if (ident != null) return ident.Context != System.Threading.Thread.CurrentContext;
231 public static bool IsOneWay(MethodBase method)
233 object[] atts = method.GetCustomAttributes (typeof (OneWayAttribute), false);
234 return atts.Length > 0;
237 public static void SetObjectUriForMarshal(MarshalByRefObject obj, string uri)
239 if (IsTransparentProxy (obj)) throw new RemotingException ("SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.");
243 #region Internal Methods
245 internal static Identity GetIdentityForUri (string uri)
249 return (Identity)uri_hash [uri];
253 internal static Identity GetObjectIdentity (MarshalByRefObject obj)
255 if (IsTransparentProxy(obj))
256 return GetRealProxy (obj).ObjectIdentity;
258 return obj.ObjectIdentity;
261 private static ClientIdentity GetClientIdentity(Type requiredType, string url, object channelData, string remotedObjectUri)
263 // This method looks for an identity for the given url.
264 // If an identity is not found, it creates the identity and
265 // assigns it a proxy to the remote object.
267 // Creates the client sink chain for the given url or channelData.
268 // It will also get the object uri from the url.
271 IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
275 string msg = String.Format ("Cannot create channel sink to connect to URL {0}. An appropriate channel has probably not been registered.", url);
276 throw new RemotingException (msg);
279 string msg = String.Format ("Cannot create channel sink to connect to the remote object. An appropriate channel has probably not been registered.", url);
280 throw new RemotingException (msg);
284 if (objectUri == null) objectUri = remotedObjectUri;
288 ClientIdentity identity = uri_hash [objectUri] as ClientIdentity;
289 if (identity != null)
290 return identity; // Object already registered
292 // Creates an identity and a proxy for the remote object
294 identity = new ClientIdentity (objectUri, requiredType);
295 identity.ClientSink = sink;
297 RemotingProxy proxy = new RemotingProxy (requiredType, identity);
299 identity.ClientProxy = (MarshalByRefObject) proxy.GetTransparentProxy();
301 // Registers the identity
302 uri_hash [objectUri] = identity;
307 internal static ClientActivatedIdentity CreateClientActivatedServerIdentity(MarshalByRefObject realObject, Type objectType, string objectUri)
309 ClientActivatedIdentity identity = new ClientActivatedIdentity (objectUri, Context.DefaultContext, objectType);
310 identity.AttachServerObject (realObject);
311 RegisterServerIdentity (identity);
315 internal static ServerIdentity CreateWellKnownServerIdentity(Type objectType, string objectUri, WellKnownObjectMode mode)
317 ServerIdentity identity;
319 if (mode == WellKnownObjectMode.SingleCall)
320 identity = new SingleCallIdentity(objectUri, Context.DefaultContext, objectType);
322 identity = new SingletonIdentity(objectUri, Context.DefaultContext, objectType);
324 RegisterServerIdentity (identity);
328 private static void RegisterServerIdentity(Identity identity)
332 if (uri_hash.ContainsKey (identity.ObjectUri))
333 throw new RemotingException ("Uri already in use: " + identity.ObjectUri);
335 uri_hash[identity.ObjectUri] = identity;
339 internal static object GetRemoteObject(Type requiredType, string url, object channelData, string remotedObjectUri)
341 ClientIdentity id = GetClientIdentity(requiredType, url, channelData, remotedObjectUri);
342 return id.ClientProxy;
345 internal static object GetDomainProxy(AppDomain domain)
\r
347 ObjRef appRef = null;
\r
349 // Make sure that the channels is active in this domain
\r
350 RegisterInternalChannels();
\r
352 // this should use contexts in the future
\r
353 AppDomain currentDomain = AppDomain.InternalSetDomain (domain);
\r
356 // Make sure that our new domain also has the internal channels
\r
357 RegisterInternalChannels();
\r
359 appRef = RemotingServices.Marshal(domain, null, null);
\r
363 AppDomain.InternalSetDomain (currentDomain);
\r
366 return (AppDomain) RemotingServices.Unmarshal(appRef);
\r
369 private static void RegisterInternalChannels()
\r
371 CrossAppDomainChannel.RegisterCrossAppDomainChannel();
\r
374 internal static void DisposeIdentity (Identity ident)
376 uri_hash.Remove (ident.ObjectUri);
379 internal static ServerIdentity GetMessageTargetIdentity (IMessage msg)
381 // Returns the identity where the message is sent
382 // TODO: check for identity embedded in MethodCall
386 return uri_hash [((IMethodMessage)msg).Uri] as ServerIdentity;