e409e8a4d38f2609ec91d363efc3a7dde7b84ed6
[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         public class RemotingProxy : RealProxy 
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.CallType == CallType.EndInvoke)
52                                 return mMsg.AsyncResult.EndInvoke ();
53
54                         if (mMsg.MethodBase.IsConstructor)
55                                 return ActivateRemoteObject (mMsg);
56
57                         if (mMsg.MethodBase == _cache_GetHashCodeMethod)
58                                 return new MethodResponse(ObjectIdentity.GetHashCode(), null, null, request as IMethodCallMessage);
59
60                         if (mMsg.MethodBase == _cache_GetTypeMethod)
61                                 return new MethodResponse(GetProxiedType(), null, null, request as IMethodCallMessage);
62
63                         mMsg.Uri = _targetUri;
64                         ((IInternalMessage)mMsg).TargetIdentity = _objectIdentity;
65
66                         _objectIdentity.NotifyClientDynamicSinks (true, request, true, false);
67
68                         IMessage response;
69                         IMessageSink sink;
70
71                         // Needs to go through the client context sink?
72                         if (Thread.CurrentContext.HasExitSinks && !_hasEnvoySink)
73                                 sink = Thread.CurrentContext.GetClientContextSinkChain ();
74                         else
75                                 sink = _sink;
76
77                         if (mMsg.CallType == CallType.Sync)
78                                 response = sink.SyncProcessMessage (request);
79                         else
80                         {
81                                 AsyncResult ares = ((MonoMethodMessage)request).AsyncResult;
82                                 IMessageCtrl mctrl = sink.AsyncProcessMessage (request, ares);
83                                 if (ares != null) ares.SetMessageCtrl (mctrl);
84                                 response = new ReturnMessage (null, new object[0], 0, null, mMsg);
85                         }
86
87                         _objectIdentity.NotifyClientDynamicSinks (false, request, true, false);
88
89                         return response;
90                 }
91
92                 internal void AttachIdentity (Identity identity)
93                 {
94                         _objectIdentity = identity;
95
96                         if (identity is ClientActivatedIdentity)        // It is a CBO
97                         {
98                                 ClientActivatedIdentity cai = (ClientActivatedIdentity)identity;
99                                 _targetContext = cai.Context;
100                                 AttachServer (cai.GetServerObject ());
101                         }
102
103                         if (identity is ClientIdentity)
104                         {
105                                 ((ClientIdentity)identity).ClientProxy = (MarshalByRefObject) GetTransparentProxy();
106                                 _targetUri = ((ClientIdentity)identity).TargetUri;
107                         }
108                         else
109                                 _targetUri = identity.ObjectUri;
110
111                         if (_objectIdentity.EnvoySink != null) 
112                         {
113                                 _sink = _objectIdentity.EnvoySink;
114                                 _hasEnvoySink = true;
115                         }
116                         else 
117                                 _sink = _objectIdentity.ChannelSink;
118
119                         _ctorCall = null;       // Object already constructed
120                 }
121
122                 IMessage ActivateRemoteObject (IMethodMessage request)
123                 {
124                         if (_ctorCall == null)  // It must be a WKO
125                                 return new ReturnMessage (this, new object[0], 0, null, (IMethodCallMessage) request);  // Ignore constructor call for WKOs
126
127                         _ctorCall.CopyFrom (request);
128                         return ActivationServices.Activate (this, _ctorCall);
129                 }
130                 
131                 ~RemotingProxy()
132                 {
133                         if (_objectIdentity != null)
134                                 RemotingServices.DisposeIdentity (_objectIdentity);
135                 }
136                 
137         }
138 }