[mini] execute decompose_typechecks only if there's a typecheck operation
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / MonoMethodMessage.cs
1 //
2 // System.Runtime.Remoting.Messaging.MonoMethodMessage.cs
3 //
4 // Author:
5 //   Dietmar Maurer (dietmar@ximian.com)
6 //   Patrik Torstensson
7 //
8 // (C) Ximian, Inc.  http://www.ximian.com
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36 using System.Reflection;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39
40 namespace System.Runtime.Remoting.Messaging {
41         
42         [Serializable]
43         [StructLayout (LayoutKind.Sequential)]
44         internal class MonoMethodMessage : IMethodCallMessage, IMethodReturnMessage, IInternalMessage {
45
46 #pragma warning disable 649
47                 #region keep in sync with MonoMessage in object-internals.h
48                 MonoMethod method;
49                 object []  args;
50                 string []  names;
51                 byte [] arg_types; /* 1 == IN; 2 == OUT; 3 == INOUT; 4 == COPY OUT */
52                 public LogicalCallContext ctx;
53                 public object rval;
54                 public Exception exc;
55                 AsyncResult asyncResult;
56                 CallType call_type;
57                 #endregion
58 #pragma warning restore 649
59
60                 string uri;
61
62                 MCMDictionary properties;
63
64                 Type[] methodSignature;
65
66                 Identity identity;
67
68                 internal static String CallContextKey = "__CallContext";
69                 internal static String UriKey           = "__Uri";
70
71                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72                 internal extern void InitMessage (MonoMethod method, object [] out_args);
73
74                 public MonoMethodMessage (MethodBase method, object [] out_args)
75                 {
76                         if (method != null)
77                                 InitMessage ((MonoMethod)method, out_args);
78                         else
79                                 args = null;
80                 }
81
82                 public MonoMethodMessage (Type type, string method_name, object [] in_args)
83                 {
84                         // fixme: consider arg types
85                         MethodInfo minfo = type.GetMethod (method_name);
86                         
87                         InitMessage ((MonoMethod)minfo, null);
88
89                         int len = in_args.Length;
90                         for (int i = 0; i < len; i++) {
91                                 args [i] = in_args [i];
92                         }
93                 }
94                 
95                 public IDictionary Properties {
96                         get {
97                                 if (properties == null) properties = new MCMDictionary (this);
98                                 return properties;
99                         }
100                 }
101
102                 public int ArgCount {
103                         get {
104                                 if (CallType == CallType.EndInvoke)
105                                         return -1;
106                                         
107                                 if (null == args)
108                                         return 0;
109
110                                 return args.Length;
111                         }
112                 }
113                 
114                 public object [] Args {
115                         get {
116                                 return args;
117                         }
118                 }
119                 
120                 public bool HasVarArgs {
121                         get {
122                                 return false;
123                         }
124                 }
125
126                 public LogicalCallContext LogicalCallContext {
127                         get {
128                                 return ctx;
129                         }
130
131                         set {
132                                 ctx = value;
133                         }
134                 }
135
136                 public MethodBase MethodBase {
137                         get {
138                                 return method;
139                         }
140                 }
141
142                 public string MethodName {
143                         get {
144                                 if (null == method)
145                                         return String.Empty;
146
147                                 return method.Name;
148                         }
149                 }
150
151                 public object MethodSignature {
152                         get {
153                                 if (methodSignature == null) {
154                                         ParameterInfo[] parameters = method.GetParameters();
155                                         methodSignature = new Type[parameters.Length];
156                                         for (int n=0; n<parameters.Length; n++)
157                                                 methodSignature[n] = parameters[n].ParameterType;
158                                 }
159                                 return methodSignature;
160                         }
161                 }
162
163                 public string TypeName {
164                         get {
165                                 if (null == method)
166                                         return String.Empty;
167
168                                 return method.DeclaringType.AssemblyQualifiedName;
169                         }
170                 }
171
172                 public string Uri {
173                         get {
174                                 return uri;
175                         }
176
177                         set {
178                                 uri = value;
179                         }
180                 }
181
182                 public object GetArg (int arg_num)
183                 {
184                         if (null == args)
185                                 return null;
186
187                         return args [arg_num];
188                 }
189                 
190                 public string GetArgName (int arg_num)
191                 {
192                         if (null == args)
193                                 return String.Empty;
194
195                         return names [arg_num];
196                 }
197
198                 public int InArgCount {
199                         get {
200                                 if (CallType == CallType.EndInvoke)
201                                         return -1;
202
203                                 if (null == args)
204                                         return 0;
205
206                                 int count = 0;
207
208                                 foreach (byte t in arg_types) {
209                                         if ((t & 1) != 0) count++;
210                                                 
211                                 }
212                                 return count;
213                         }
214                 }
215                 
216                 public object [] InArgs {
217                         get {                
218                                 int i, j, count = InArgCount;
219                                 object [] inargs = new object [count];
220
221                                 i = j = 0;
222                                 foreach (byte t in arg_types) {
223                                         if ((t & 1) != 0)
224                                                 inargs [j++] = args [i];
225                                         i++;
226                                 }
227                                 
228                                 return inargs;
229                         }
230                 }
231                 
232                 public object GetInArg (int arg_num)
233                 {
234                         int i = 0, j = 0;
235                         foreach (byte t in arg_types) {
236                                 if ((t & 1) != 0) {
237                                         if (j++ == arg_num)
238                                                 return args [i]; 
239                                 }
240                                 i++;
241                         }
242                         return null;
243                 }
244                 
245                 public string GetInArgName (int arg_num)
246                 {
247                         int i = 0, j = 0;
248                         foreach (byte t in arg_types) {
249                                 if ((t & 1) != 0) {
250                                         if (j++ == arg_num)
251                                                 return names [i]; 
252                                 }
253                                 i++;
254                         }
255                         return null;
256                 }
257
258                 public Exception Exception {
259                         get {
260                                 return exc;
261                         }
262                 }
263                 
264                 public int OutArgCount {
265                         get {
266                                 if (null == args)
267                                         return 0;
268                                 
269                                 int count = 0;
270
271                                 foreach (byte t in arg_types) {
272                                         if ((t & 2) != 0) count++;
273                                                 
274                                 }
275                                 return count;
276                         }
277                 }
278                 
279                 public object [] OutArgs {
280                         get {
281                                 if (null == args)
282                                         return null;
283
284                                 int i, j, count = OutArgCount;
285                                 object [] outargs = new object [count];
286
287                                 i = j = 0;
288                                 foreach (byte t in arg_types) {
289                                         if ((t & 2) != 0)
290                                                 outargs [j++] = args [i];
291                                         i++;
292                                 }
293                                 
294                                 return outargs;
295                         }
296                 }
297                 
298                 public object ReturnValue {
299                         get {
300                                 return rval;
301                         }
302                 }
303
304                 public object GetOutArg (int arg_num)
305                 {
306                         int i = 0, j = 0;
307                         foreach (byte t in arg_types) {
308                                 if ((t & 2) != 0) {
309                                         if (j++ == arg_num)
310                                                 return args [i]; 
311                                 }
312                                 i++;
313                         }
314                         return null;
315                 }
316                 
317                 public string GetOutArgName (int arg_num)
318                 {
319                         int i = 0, j = 0;
320                         foreach (byte t in arg_types) {
321                                 if ((t & 2) != 0) {
322                                         if (j++ == arg_num)
323                                                 return names [i]; 
324                                 }
325                                 i++;
326                         }
327                         return null;
328                 }
329
330                 Identity IInternalMessage.TargetIdentity
331                 {
332                         get { return identity; }
333                         set { identity = value; }
334                 }
335
336                 bool IInternalMessage.HasProperties()
337                 {
338                         return properties != null;
339                 }
340
341                 public bool IsAsync
342                 {
343                         get { return asyncResult != null; }
344                 }
345
346                 public AsyncResult AsyncResult
347                 {
348                         get { return asyncResult; }
349                 }
350
351                 internal CallType CallType
352                 {
353                         get
354                         {
355                                 // FIXME: ideally, the OneWay type would be set by the runtime
356                                 
357                                 if (call_type == CallType.Sync && RemotingServices.IsOneWay (method))
358                                         call_type = CallType.OneWay;
359                                 return call_type;
360                         }
361                 }
362                 
363                 public bool NeedsOutProcessing (out int outCount) {
364                         bool res = false;
365                         outCount = 0;
366                         foreach (byte t in arg_types) {
367                                 if ((t & 2) != 0)
368                                         outCount++;
369                                 else if ((t & 4) != 0)
370                                         res = true;
371                         }
372                         return outCount > 0 || res;
373                 }
374                 
375         }
376
377         internal enum CallType: int
378         {
379                 Sync = 0,
380                 BeginInvoke = 1,
381                 EndInvoke = 2,
382                 OneWay = 3
383         }
384 }
385