5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2011 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #if !DISABLE_REAL_PROXY
30 using System.Collections.Generic;
32 using System.Reflection;
33 using System.Runtime.Remoting;
34 using System.Runtime.Remoting.Messaging;
35 using System.Runtime.Remoting.Proxies;
36 using System.ServiceModel.Channels;
37 using System.ServiceModel.Description;
38 using System.ServiceModel.Dispatcher;
39 using System.ServiceModel.MonoInternal;
40 using System.Threading;
42 namespace System.ServiceModel
44 class ClientRealProxy : RealProxy, IRemotingTypeInfo
46 public ClientRealProxy (Type type, IInternalContextChannel channel, bool isDuplex)
49 this.channel = channel;
51 context_channel_type = typeof (IClientChannel);
53 context_channel_type = isDuplex ? typeof (IDuplexContextChannel) : typeof (IClientChannel);
57 Type context_channel_type;
58 IInternalContextChannel channel;
59 Dictionary<object,object[]> saved_params = new Dictionary<object,object[]> ();
61 // It is used for such case that EndProcess() gets invoked
62 // before storing params is done after BeginProcess().
63 ManualResetEvent wait = new ManualResetEvent (false);
65 #region IRemotingTypeInfo
67 public virtual string TypeName { get; set; }
69 public virtual bool CanCastTo (Type t, object o)
71 if (t == context_channel_type || context_channel_type.GetInterfaces ().Contains (t))
78 public override IMessage Invoke (IMessage inputMessage)
81 return DoInvoke (inputMessage);
82 } catch (TargetInvocationException ex) {
83 if (ex.InnerException != null)
84 throw ex.InnerException;
89 IMessage DoInvoke (IMessage inputMessage)
91 var inmsg = (IMethodCallMessage) inputMessage;
92 var od = channel.Contract.Operations.FirstOrDefault (o => inmsg.MethodBase.Equals (o.SyncMethod) || inmsg.MethodBase.Equals (o.BeginMethod) || inmsg.MethodBase.Equals (o.EndMethod));
94 // Then IContextChannel methods.
95 var ret = inmsg.MethodBase.Invoke (channel, inmsg.InArgs);
96 return new ReturnMessage (ret, null, 0, null, inmsg);
99 MethodBase method = null;
100 List<object> outArgs = null;
102 if (inmsg.MethodBase.Equals (od.SyncMethod)) {
104 pl = new object [inmsg.MethodBase.GetParameters ().Length];
105 Array.Copy (inmsg.Args, pl, inmsg.ArgCount);
106 ret = channel.Process (inmsg.MethodBase, od.Name, pl);
107 method = od.SyncMethod;
108 } else if (inmsg.MethodBase.Equals (od.BeginMethod)) {
110 pl = new object [inmsg.ArgCount - 2];
111 Array.Copy (inmsg.Args, 0, pl, 0, pl.Length);
113 ret = channel.BeginProcess (inmsg.MethodBase, od.Name, pl, (AsyncCallback) inmsg.Args [inmsg.ArgCount - 2], inmsg.Args [inmsg.ArgCount - 1]);
114 saved_params [ret] = pl;
119 var result = (IAsyncResult) inmsg.InArgs [0];
122 pl = saved_params [result];
124 saved_params.Remove (result);
125 ret = channel.EndProcess (inmsg.MethodBase, od.Name, pl, result);
126 method = od.BeginMethod;
129 if (method != null && method.GetParameters ().Any (pi => pi.IsOut))
130 return new ReturnMessage (ret, pl, pl.Length, null, inmsg);
132 return new ReturnMessage (ret, outArgs != null ? outArgs.ToArray () : null, outArgs != null ? outArgs.Count : 0, null, inmsg);