* ProxyAttribute.cs: Implemented.
[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");\r
27                 static MethodInfo _cache_GetHashCodeMethod = typeof(System.Object).GetMethod("GetHashCode");\r
28 \r
29                 IMessageSink _sink;
30                 string _activationUrl;
31                 bool _hasEnvoySink;
32                 ConstructionCall _ctorCall;
33
34                 internal RemotingProxy (Type type, ClientIdentity identity) : base (type, identity)
35                 {
36                         _sink = identity.ChannelSink;
37                         _hasEnvoySink = false;
38                 }
39
40                 internal RemotingProxy (Type type, string activationUrl, object[] activationAttributes) : base (type)
41                 {
42                         _activationUrl = activationUrl;
43                         _hasEnvoySink = false;
44
45                         _ctorCall = ActivationServices.CreateConstructionCall (type, activationUrl, activationAttributes);
46                 }
47
48                 public override IMessage Invoke (IMessage request)
49                 {
50                         MonoMethodMessage mMsg = (MonoMethodMessage) request;
51
52                         if (mMsg.MethodBase.IsConstructor)
53                                 return ActivateRemoteObject (mMsg);
54
55                         if (mMsg.MethodBase == _cache_GetHashCodeMethod)
56                                 return new MethodResponse(ObjectIdentity.GetHashCode(), null, null, request as IMethodCallMessage);\r
57
58                         if (mMsg.MethodBase == _cache_GetTypeMethod)
59                                 return new MethodResponse(GetProxiedType(), null, null, request as IMethodCallMessage);\r
60
61                         mMsg.Uri = _objectIdentity.ObjectUri;
62                         ((IInternalMessage)mMsg).TargetIdentity = _objectIdentity;
63
64                         // Exiting from the context?
65                         if (!Thread.CurrentContext.IsDefaultContext && !_hasEnvoySink)
66                                 return Thread.CurrentContext.GetClientContextSinkChain ().SyncProcessMessage (request);
67                         else
68                                 return _sink.SyncProcessMessage (request);
69                 }
70
71                 IMessage ActivateRemoteObject (IMethodMessage request)
72                 {
73                         if (_activationUrl == null)
74                                 return new ReturnMessage (this, new object[0], 0, null, (IMethodCallMessage) request);  // Ignore constructor call for WKOs
75
76                         IMethodReturnMessage response;
77
78                         _ctorCall.CopyFrom (request);
79
80                         if (_activationUrl == ChannelServices.CrossContextUrl)
81                         {
82                                 // Cross context activation
83
84                                 _objectIdentity = RemotingServices.CreateContextBoundObjectIdentity (_ctorCall.ActivationType);
85                                 RemotingServices.SetMessageTargetIdentity (_ctorCall, _objectIdentity);
86                                 response = _ctorCall.Activator.Activate (_ctorCall);
87                         }
88                         else
89                         {
90                                 // Remote activation
91
92                                 RemoteActivator remoteActivator = (RemoteActivator) RemotingServices.Connect (typeof (RemoteActivator), _activationUrl);
93
94                                 try {
95                                         response = remoteActivator.Activate (_ctorCall) as IMethodReturnMessage;
96                                 }
97                                 catch (Exception ex) {
98                                         return new ReturnMessage (ex, (IMethodCallMessage)request);
99                                 }
100
101                                 ObjRef objRef = (ObjRef) response.ReturnValue;
102                                 if (RemotingServices.GetIdentityForUri (objRef.URI) != null)
103                                         throw new RemotingException("Inconsistent state during activation; there may be two proxies for the same object");
104
105                                 _objectIdentity = RemotingServices.GetOrCreateClientIdentity (objRef, this);
106                         }
107
108                         if (_objectIdentity.EnvoySink != null) 
109                         {
110                                 _sink = _objectIdentity.EnvoySink;
111                                 _hasEnvoySink = true;
112                         }
113                         else 
114                                 _sink = _objectIdentity.ChannelSink;
115
116                         _activationUrl = null;
117                         _ctorCall = null;
118                         return response;
119                 }
120         }
121 }