a01be8f8a649a39da26093aed35780b4c5fd7f02
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Proxies / RemotingProxy.cs
1 //
2 // System.Runtime.Remoting.Proxies.RemotingProxy.cs
3 //
4 // Authors:
5 //   Dietmar Maurer (dietmar@ximian.com)
6 //   Lluis Sanchez Gual (lsg@ctv.es)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Runtime.Remoting.Messaging;
14 using System.Runtime.Remoting.Activation;
15 using System.Runtime.Remoting.Channels;
16 using System.Runtime.Remoting.Contexts;
17 using System.Runtime.CompilerServices;
18 using System.Threading;
19
20
21 namespace System.Runtime.Remoting.Proxies
22 {
23
24         internal class RemotingProxy : RealProxy, IRemotingTypeInfo
25         {
26                 static MethodInfo _cache_GetTypeMethod = typeof(System.Object).GetMethod("GetType");
27                 static MethodInfo _cache_GetHashCodeMethod = typeof(System.Object).GetMethod("GetHashCode");
28
29                 IMessageSink _sink;
30                 bool _hasEnvoySink;
31                 ConstructionCall _ctorCall;
32                 string _targetUri;
33
34                 internal RemotingProxy (Type type, ClientIdentity identity) : base (type, identity)
35                 {
36                         _sink = identity.ChannelSink;
37                         _hasEnvoySink = false;
38                         _targetUri = identity.TargetUri;
39                 }
40
41                 internal RemotingProxy (Type type, string activationUrl, object[] activationAttributes) : base (type)
42                 {
43                         _hasEnvoySink = false;
44                         _ctorCall = ActivationServices.CreateConstructionCall (type, activationUrl, activationAttributes);
45                 }
46
47                 public override IMessage Invoke (IMessage request)
48                 {
49                         MonoMethodMessage mMsg = (MonoMethodMessage) request;
50
51                         if (mMsg.MethodBase == _cache_GetHashCodeMethod)
52                                 return new MethodResponse(ObjectIdentity.GetHashCode(), null, null, request as IMethodCallMessage);
53
54                         if (mMsg.MethodBase == _cache_GetTypeMethod)
55                                 return new MethodResponse(GetProxiedType(), null, null, request as IMethodCallMessage);
56
57                         mMsg.Uri = _targetUri;
58                         ((IInternalMessage)mMsg).TargetIdentity = _objectIdentity;
59
60                         _objectIdentity.NotifyClientDynamicSinks (true, request, true, false);
61
62                         IMessage response;
63                         IMessageSink sink;
64
65                         // Needs to go through the client context sink?
66                         if (Thread.CurrentContext.HasExitSinks && !_hasEnvoySink)
67                                 sink = Thread.CurrentContext.GetClientContextSinkChain ();
68                         else
69                                 sink = _sink;
70
71                         if (mMsg.CallType == CallType.Sync)
72                                 response = sink.SyncProcessMessage (request);
73                         else
74                         {
75                                 AsyncResult ares = mMsg.AsyncResult;
76                                 IMessageCtrl mctrl = sink.AsyncProcessMessage (request, ares);
77                                 if (ares != null) ares.SetMessageCtrl (mctrl);
78                                 response = new ReturnMessage (null, new object[0], 0, null, mMsg);
79                         }
80
81                         _objectIdentity.NotifyClientDynamicSinks (false, request, true, false);
82
83                         return response;
84                 }
85
86                 internal void AttachIdentity (Identity identity)
87                 {
88                         _objectIdentity = identity;
89
90                         if (identity is ClientActivatedIdentity)        // It is a CBO
91                         {
92                                 ClientActivatedIdentity cai = (ClientActivatedIdentity)identity;
93                                 _targetContext = cai.Context;
94                                 AttachServer (cai.GetServerObject ());
95                         }
96
97                         if (identity is ClientIdentity)
98                         {
99                                 ((ClientIdentity)identity).ClientProxy = (MarshalByRefObject) GetTransparentProxy();
100                                 _targetUri = ((ClientIdentity)identity).TargetUri;
101                         }
102                         else
103                                 _targetUri = identity.ObjectUri;
104
105                         if (_objectIdentity.EnvoySink != null)
106                         {
107                                 _sink = _objectIdentity.EnvoySink;
108                                 _hasEnvoySink = true;
109                         }
110                         else 
111                                 _sink = _objectIdentity.ChannelSink;
112
113                         _ctorCall = null;       // Object already constructed
114                 }
115
116                 internal IMessage ActivateRemoteObject (IMethodMessage request)
117                 {
118                         if (_ctorCall == null)  // It must be a WKO
119                                 return new ConstructionResponse (this, null, (IMethodCallMessage) request);     // Ignore constructor call for WKOs
120
121                         _ctorCall.CopyFrom (request);
122                         return ActivationServices.Activate (this, _ctorCall);
123                 }
124
125                 public string TypeName 
126                 { 
127                         get
128                         {
129                                 if (_objectIdentity is ClientIdentity) {
130                                         ObjRef oref = _objectIdentity.CreateObjRef (null);
131                                         if (oref.TypeInfo != null) return oref.TypeInfo.TypeName;
132                                 }
133                                 return GetProxiedType().AssemblyQualifiedName;
134                         }
135                         
136                         set
137                         {
138                                 throw new NotSupportedException ();
139                         }
140                 }
141                 
142                 public bool CanCastTo (Type fromType, object o)
143                 {
144                         if (_objectIdentity is ClientIdentity) {
145                                 ObjRef oref = _objectIdentity.CreateObjRef (null);
146                                 if (oref.IsReferenceToWellKnow && (fromType.IsInterface || GetProxiedType() == typeof(MarshalByRefObject))) return true;
147                                 if (oref.TypeInfo != null) return oref.TypeInfo.CanCastTo (fromType, o);
148                         }
149                         return fromType.IsAssignableFrom (GetProxiedType());
150                 }
151                 
152                 ~RemotingProxy()
153                 {
154                         if (_objectIdentity != null)
155                         {
156                                 if (!(_objectIdentity is ClientActivatedIdentity))      // Local CBO proxy?
157                                         RemotingServices.DisposeIdentity (_objectIdentity);
158                         }
159                 }
160                 
161         }
162 }