Xamarin Public Jenkins (auto-signing) ef583813eb Imported Upstream version 6.4.0.137
Former-commit-id: 943baa9f16a098c33e129777827f3a9d20da00d6
2019-07-26 19:53:28 +00:00

436 lines
8.6 KiB
C#

//
// System.Runtime.Remoting.Messaging.MonoMethodMessage.cs
//
// Author:
// Dietmar Maurer (dietmar@ximian.com)
// Patrik Torstensson
//
// (C) Ximian, Inc. http://www.ximian.com
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Runtime.Remoting.Messaging {
[Serializable]
[StructLayout (LayoutKind.Sequential)]
internal class MonoMethodMessage
#if !DISABLE_REMOTING
: IMethodCallMessage, IMethodReturnMessage, IInternalMessage
#endif
{
#pragma warning disable 649
#region keep in sync with MonoMessage in object-internals.h
RuntimeMethodInfo method;
object [] args;
string [] names;
byte [] arg_types; /* 1 == IN; 2 == OUT; 3 == INOUT; 4 == COPY OUT */
public LogicalCallContext ctx;
public object rval;
public Exception exc;
AsyncResult asyncResult;
CallType call_type;
#endregion
#pragma warning restore 649
string uri;
#if !DISABLE_REMOTING
MCMDictionary properties;
Identity identity;
#endif
Type[] methodSignature;
internal void InitMessage (RuntimeMethodInfo method, object [] out_args)
{
this.method = method;
ParameterInfo[] paramInfo = method.GetParametersInternal ();
int param_count = paramInfo.Length;
args = new object[param_count];
arg_types = new byte[param_count];
asyncResult = null;
call_type = CallType.Sync;
names = new string[param_count];
for (int i = 0; i < param_count; i++) {
names[i] = paramInfo[i].Name;
}
bool hasOutArgs = out_args != null;
int j = 0;
for (int i = 0; i < param_count; i++) {
byte arg_type;
bool isOut = paramInfo[i].IsOut;
if (paramInfo[i].ParameterType.IsByRef) {
if (hasOutArgs)
args[i] = out_args[j++];
arg_type = 2; // OUT
if (!isOut)
arg_type |= 1; // INOUT
} else {
arg_type = 1; // IN
if (isOut)
arg_type |= 4; // IN, COPY OUT
}
arg_types[i] = arg_type;
}
}
public MonoMethodMessage (MethodBase method, object [] out_args)
{
if (method != null)
InitMessage ((RuntimeMethodInfo)method, out_args);
else
args = null;
}
internal MonoMethodMessage (MethodInfo minfo, object [] in_args, object [] out_args)
{
InitMessage ((RuntimeMethodInfo)minfo, out_args);
int len = in_args.Length;
for (int i = 0; i < len; i++) {
args [i] = in_args [i];
}
}
private static MethodInfo GetMethodInfo (Type type, string methodName)
{
// fixme: consider arg types
MethodInfo minfo = type.GetMethod(methodName);
if (minfo == null)
throw new ArgumentException (String.Format("Could not find '{0}' in {1}", methodName, type), "methodName");
return minfo;
}
public MonoMethodMessage (Type type, string methodName, object [] in_args)
: this (GetMethodInfo (type, methodName), in_args, null)
{
}
public IDictionary Properties {
get {
#if DISABLE_REMOTING
throw new PlatformNotSupportedException ();
#else
if (properties == null) properties = new MCMDictionary (this);
return properties;
#endif
}
}
public int ArgCount {
get {
if (CallType == CallType.EndInvoke)
return -1;
if (null == args)
return 0;
return args.Length;
}
}
public object [] Args {
get {
return args;
}
}
public bool HasVarArgs {
get {
return false;
}
}
public LogicalCallContext LogicalCallContext {
get {
return ctx;
}
set {
ctx = value;
}
}
public MethodBase MethodBase {
get {
return method;
}
}
public string MethodName {
get {
if (null == method)
return String.Empty;
return method.Name;
}
}
public object MethodSignature {
get {
if (methodSignature == null) {
ParameterInfo[] parameters = method.GetParameters();
methodSignature = new Type[parameters.Length];
for (int n=0; n<parameters.Length; n++)
methodSignature[n] = parameters[n].ParameterType;
}
return methodSignature;
}
}
public string TypeName {
get {
if (null == method)
return String.Empty;
return method.DeclaringType.AssemblyQualifiedName;
}
}
public string Uri {
get {
return uri;
}
set {
uri = value;
}
}
public object GetArg (int arg_num)
{
if (null == args)
return null;
return args [arg_num];
}
public string GetArgName (int arg_num)
{
if (null == args)
return String.Empty;
return names [arg_num];
}
public int InArgCount {
get {
if (CallType == CallType.EndInvoke)
return -1;
if (null == args)
return 0;
int count = 0;
foreach (byte t in arg_types) {
if ((t & 1) != 0) count++;
}
return count;
}
}
public object [] InArgs {
get {
int i, j, count = InArgCount;
object [] inargs = new object [count];
i = j = 0;
foreach (byte t in arg_types) {
if ((t & 1) != 0)
inargs [j++] = args [i];
i++;
}
return inargs;
}
}
public object GetInArg (int arg_num)
{
int i = 0, j = 0;
foreach (byte t in arg_types) {
if ((t & 1) != 0) {
if (j++ == arg_num)
return args [i];
}
i++;
}
return null;
}
public string GetInArgName (int arg_num)
{
int i = 0, j = 0;
foreach (byte t in arg_types) {
if ((t & 1) != 0) {
if (j++ == arg_num)
return names [i];
}
i++;
}
return null;
}
public Exception Exception {
get {
return exc;
}
}
public int OutArgCount {
get {
if (null == args)
return 0;
int count = 0;
foreach (byte t in arg_types) {
if ((t & 2) != 0) count++;
}
return count;
}
}
public object [] OutArgs {
get {
if (null == args)
return null;
int i, j, count = OutArgCount;
object [] outargs = new object [count];
i = j = 0;
foreach (byte t in arg_types) {
if ((t & 2) != 0)
outargs [j++] = args [i];
i++;
}
return outargs;
}
}
public object ReturnValue {
get {
return rval;
}
}
public object GetOutArg (int arg_num)
{
int i = 0, j = 0;
foreach (byte t in arg_types) {
if ((t & 2) != 0) {
if (j++ == arg_num)
return args [i];
}
i++;
}
return null;
}
public string GetOutArgName (int arg_num)
{
int i = 0, j = 0;
foreach (byte t in arg_types) {
if ((t & 2) != 0) {
if (j++ == arg_num)
return names [i];
}
i++;
}
return null;
}
#if !DISABLE_REMOTING
Identity IInternalMessage.TargetIdentity
{
get { return identity; }
set { identity = value; }
}
bool IInternalMessage.HasProperties()
{
return properties != null;
}
#endif
public bool IsAsync
{
get { return asyncResult != null; }
}
public AsyncResult AsyncResult
{
get { return asyncResult; }
}
internal CallType CallType
{
get
{
// FIXME: ideally, the OneWay type would be set by the runtime
#if !DISABLE_REMOTING
if (call_type == CallType.Sync && RemotingServices.IsOneWay (method))
call_type = CallType.OneWay;
#endif
return call_type;
}
}
public bool NeedsOutProcessing (out int outCount) {
bool res = false;
outCount = 0;
foreach (byte t in arg_types) {
if ((t & 2) != 0)
outCount++;
else if ((t & 4) != 0)
res = true;
}
return outCount > 0 || res;
}
}
internal enum CallType: int
{
Sync = 0,
BeginInvoke = 1,
EndInvoke = 2,
OneWay = 3
}
}