A little more work of CorCompare work:
[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
39 namespace System.Runtime.Remoting.Messaging {
40         
41         [Serializable]
42         internal class MonoMethodMessage : IMethodCallMessage, IMethodReturnMessage, IInternalMessage {
43
44                 #region keep in sync with MonoMessage in object-internals.h
45                 MonoMethod method;
46                 object []  args;
47                 string []  names;
48                 byte [] arg_types; /* 1 == IN; 2 == OUT; 3 == INOUT; 4 == COPY OUT */
49                 public LogicalCallContext ctx;
50                 public object rval;
51                 public Exception exc;
52                 AsyncResult asyncResult;
53                 CallType call_type;
54                 #endregion
55
56                 string uri;
57
58                 MethodCallDictionary properties;
59
60                 Type[] methodSignature;
61
62                 Identity identity;
63
64
65                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66                 internal extern void InitMessage (MonoMethod method, object [] out_args);
67
68                 public MonoMethodMessage (MethodBase method, object [] out_args)
69                 {
70                         if (method != null)
71                                 InitMessage ((MonoMethod)method, out_args);
72                         else
73                                 args = null;
74                 }
75
76                 public MonoMethodMessage (Type type, string method_name, object [] in_args)
77                 {
78                         // fixme: consider arg types
79                         MethodInfo minfo = type.GetMethod (method_name);
80                         
81                         InitMessage ((MonoMethod)minfo, null);
82
83                         int len = in_args.Length;
84                         for (int i = 0; i < len; i++) {
85                                 args [i] = in_args [i];
86                         }
87                 }
88                 
89                 public IDictionary Properties {
90                         get {
91                                 if (properties == null) properties = new MethodCallDictionary (this);
92                                 return properties;
93                         }
94                 }
95
96                 public int ArgCount {
97                         get {
98                                 if (CallType == CallType.EndInvoke)
99                                         return -1;
100                                         
101                                 if (null == args)
102                                         return 0;
103
104                                 return args.Length;
105                         }
106                 }
107                 
108                 public object [] Args {
109                         get {
110                                 return args;
111                         }
112                 }
113                 
114                 public bool HasVarArgs {
115                         get {
116                                 return false;
117                         }
118                 }
119
120                 public LogicalCallContext LogicalCallContext {
121                         get {
122                                 return ctx;
123                         }
124
125                         set {
126                                 ctx = value;
127                         }
128                 }
129
130                 public MethodBase MethodBase {
131                         get {
132                                 return method;
133                         }
134                 }
135
136                 public string MethodName {
137                         get {
138                                 if (null == method)
139                                         return String.Empty;
140
141                                 return method.Name;
142                         }
143                 }
144
145                 public object MethodSignature {
146                         get {
147                                 if (methodSignature == null) {
148                                         ParameterInfo[] parameters = method.GetParameters();
149                                         methodSignature = new Type[parameters.Length];
150                                         for (int n=0; n<parameters.Length; n++)
151                                                 methodSignature[n] = parameters[n].ParameterType;
152                                 }
153                                 return methodSignature;
154                         }
155                 }
156
157                 public string TypeName {
158                         get {
159                                 if (null == method)
160                                         return String.Empty;
161
162                                 return method.DeclaringType.AssemblyQualifiedName;
163                         }
164                 }
165
166                 public string Uri {
167                         get {
168                                 return uri;
169                         }
170
171                         set {
172                                 uri = value;
173                         }
174                 }
175
176                 public object GetArg (int arg_num)
177                 {
178                         if (null == args)
179                                 return null;
180
181                         return args [arg_num];
182                 }
183                 
184                 public string GetArgName (int arg_num)
185                 {
186                         if (null == args)
187                                 return String.Empty;
188
189                         return names [arg_num];
190                 }
191
192                 public int InArgCount {
193                         get {
194                                 if (CallType == CallType.EndInvoke)
195                                         return -1;
196
197                                 if (null == args)
198                                         return 0;
199
200                                 int count = 0;
201
202                                 foreach (byte t in arg_types) {
203                                         if ((t & 1) != 0) count++;
204                                                 
205                                 }
206                                 return count;
207                         }
208                 }
209                 
210                 public object [] InArgs {
211                         get {                
212                                 int i, j, count = InArgCount;
213                                 object [] inargs = new object [count];
214
215                                 i = j = 0;
216                                 foreach (byte t in arg_types) {
217                                         if ((t & 1) != 0)
218                                                 inargs [j++] = args [i];
219                                         i++;
220                                 }
221                                 
222                                 return inargs;
223                         }
224                 }
225                 
226                 public object GetInArg (int arg_num)
227                 {
228                         int i = 0, j = 0;
229                         foreach (byte t in arg_types) {
230                                 if ((t & 1) != 0) {
231                                         if (j++ == arg_num)
232                                                 return args [i]; 
233                                 }
234                                 i++;
235                         }
236                         return null;
237                 }
238                 
239                 public string GetInArgName (int arg_num)
240                 {
241                         int i = 0, j = 0;
242                         foreach (byte t in arg_types) {
243                                 if ((t & 1) != 0) {
244                                         if (j++ == arg_num)
245                                                 return names [i]; 
246                                 }
247                                 i++;
248                         }
249                         return null;
250                 }
251
252                 public Exception Exception {
253                         get {
254                                 return exc;
255                         }
256                 }
257                 
258                 public int OutArgCount {
259                         get {
260                                 if (null == args)
261                                         return 0;
262                                 
263                                 int count = 0;
264
265                                 foreach (byte t in arg_types) {
266                                         if ((t & 2) != 0) count++;
267                                                 
268                                 }
269                                 return count;
270                         }
271                 }
272                 
273                 public object [] OutArgs {
274                         get {
275                                 if (null == args)
276                                         return null;
277
278                                 int i, j, count = OutArgCount;
279                                 object [] outargs = new object [count];
280
281                                 i = j = 0;
282                                 foreach (byte t in arg_types) {
283                                         if ((t & 2) != 0)
284                                                 outargs [j++] = args [i];
285                                         i++;
286                                 }
287                                 
288                                 return outargs;
289                         }
290                 }
291                 
292                 public object ReturnValue {
293                         get {
294                                 return rval;
295                         }
296                 }
297
298                 public object GetOutArg (int arg_num)
299                 {
300                         int i = 0, j = 0;
301                         foreach (byte t in arg_types) {
302                                 if ((t & 2) != 0) {
303                                         if (j++ == arg_num)
304                                                 return args [i]; 
305                                 }
306                                 i++;
307                         }
308                         return null;
309                 }
310                 
311                 public string GetOutArgName (int arg_num)
312                 {
313                         int i = 0, j = 0;
314                         foreach (byte t in arg_types) {
315                                 if ((t & 2) != 0) {
316                                         if (j++ == arg_num)
317                                                 return names [i]; 
318                                 }
319                                 i++;
320                         }
321                         return null;
322                 }
323
324                 Identity IInternalMessage.TargetIdentity
325                 {
326                         get { return identity; }
327                         set { identity = value; }
328                 }
329
330                 public bool IsAsync
331                 {
332                         get { return asyncResult != null; }
333                 }
334
335                 public AsyncResult AsyncResult
336                 {
337                         get { return asyncResult; }
338                 }
339
340                 internal CallType CallType
341                 {
342                         get
343                         {
344                                 // FIXME: ideally, the OneWay type would be set by the runtime
345                                 
346                                 if (call_type == CallType.Sync && RemotingServices.IsOneWay (method))
347                                         call_type = CallType.OneWay;
348                                 return call_type;
349                         }
350                 }
351                 
352                 public bool NeedsOutProcessing (out int outCount) {
353                         bool res = false;
354                         outCount = 0;
355                         foreach (byte t in arg_types) {
356                                 if ((t & 2) != 0)
357                                         outCount++;
358                                 else if ((t & 4) != 0)
359                                         res = true;
360                         }
361                         return outCount > 0 || res;
362                 }
363                 
364         }
365
366         internal enum CallType: int
367         {
368                 Sync = 0,
369                 BeginInvoke = 1,
370                 EndInvoke = 2,
371                 OneWay = 3
372         }
373 }
374