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;
50 this.isDuplex = isDuplex;
54 IInternalContextChannel channel;
55 Dictionary<object,object[]> saved_params = new Dictionary<object,object[]> ();
57 // It is used for such case that EndProcess() gets invoked
58 // before storing params is done after BeginProcess().
59 ManualResetEvent wait = new ManualResetEvent (false);
61 #region IRemotingTypeInfo
63 public virtual string TypeName { get; set; }
65 static bool CanCastTo<T> (Type type)
67 return typeof (T) == type || typeof (T).GetInterfaces ().Contains (type);
70 public virtual bool CanCastTo (Type t, object o)
72 if (CanCastTo<IClientChannel> (t))
75 if (isDuplex && CanCastTo<IDuplexContextChannel> (t))
83 public override IMessage Invoke (IMessage inputMessage)
86 return DoInvoke (inputMessage);
87 } catch (TargetInvocationException ex) {
88 if (ex.InnerException != null)
89 throw ex.InnerException;
94 IMessage DoInvoke (IMessage inputMessage)
96 var inmsg = (IMethodCallMessage) inputMessage;
97 var od = channel.Contract.Operations.FirstOrDefault (o => inmsg.MethodBase.Equals (o.SyncMethod) || inmsg.MethodBase.Equals (o.BeginMethod) || inmsg.MethodBase.Equals (o.EndMethod));
99 // Then IContextChannel methods.
100 var ret = inmsg.MethodBase.Invoke (channel, inmsg.InArgs);
101 return new ReturnMessage (ret, null, 0, null, inmsg);
104 MethodBase method = null;
105 List<object> outArgs = null;
107 if (inmsg.MethodBase.Equals (od.SyncMethod)) {
109 pl = new object [inmsg.MethodBase.GetParameters ().Length];
110 Array.Copy (inmsg.Args, pl, inmsg.ArgCount);
111 ret = channel.Process (inmsg.MethodBase, od.Name, pl, OperationContext.Current);
112 method = od.SyncMethod;
113 } else if (inmsg.MethodBase.Equals (od.BeginMethod)) {
115 pl = new object [inmsg.ArgCount - 2];
116 Array.Copy (inmsg.Args, 0, pl, 0, pl.Length);
118 ret = channel.BeginProcess (inmsg.MethodBase, od.Name, pl, (AsyncCallback) inmsg.Args [inmsg.ArgCount - 2], inmsg.Args [inmsg.ArgCount - 1]);
119 saved_params [ret] = pl;
124 var result = (IAsyncResult) inmsg.InArgs [0];
127 pl = saved_params [result];
129 saved_params.Remove (result);
130 ret = channel.EndProcess (inmsg.MethodBase, od.Name, pl, result);
131 method = od.BeginMethod;
134 if (method != null && method.GetParameters ().Any (pi => pi.IsOut || pi.ParameterType.IsByRef))
135 return new ReturnMessage (ret, pl, pl.Length, null, inmsg);
137 return new ReturnMessage (ret, outArgs != null ? outArgs.ToArray () : null, outArgs != null ? outArgs.Count : 0, null, inmsg);