using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;
using Pegasus.Diagnostics;
using Pegasus.Runtime.Serialization;
namespace Pegasus.Runtime.Remoting.Messaging
{
/// <summary>
/// Internal class for passing messages as part of the remoting sinks.
/// </summary>
[Serializable]
internal class PegasusMethodCall : IMethodCallMessage, IMethodReturnMessage, ISerializable
{
// Local Instance Values
private IDictionary m_properties;
private object[] m_inArgs = new object[ 0 ];
private string[] m_inArgsNames = new string[ 0 ];
private object[] m_args = new object[ 0 ];
private string[] m_argsNames = new string[ 0 ];
private object[] m_outArgs = new object[ 0 ];
private string[] m_outArgsNames = new string[ 0 ];
private bool m_hasVarArgs = false;
private LogicalCallContext m_logicalCallContext = null;
private string m_methodUri = null;
private object m_returnValue = null;
private Exception m_exception = null;
private MethodInfo m_methodInfo = null;
// Local Static Values
private static ObjectSerializationBinder s_binder = new ObjectSerializationBinder();
/// <summary>
/// Initializes a new instance of the <see cref="PegasusMethodCall"/> class.
/// </summary>
/// <param name="message">The message.</param>
public PegasusMethodCall( IMessage message )
{
// Check Parameters
ParamCode.AssertNotNull( message, "message" );
// Get references to all the values of the message object
IDictionary properties = message.Properties;
m_properties = new Hashtable();
foreach( object key in properties.Keys )
{
m_properties.Add( key, properties[ key ] );
}
if( message is IMethodMessage )
{
IMethodMessage methodMessage = (IMethodMessage) message;
m_args = methodMessage.Args;
int count = m_args.Length;
m_argsNames = new string[ count ];
for( int x = 0; x < count; x++ )
{
m_argsNames[ x ] = methodMessage.GetArgName( x );
}
m_hasVarArgs = methodMessage.HasVarArgs;
m_logicalCallContext = methodMessage.LogicalCallContext;
m_methodUri = methodMessage.Uri;
m_methodInfo = (MethodInfo) methodMessage.MethodBase;
if( message is IMethodCallMessage )
{
IMethodCallMessage methodCall = (IMethodCallMessage) message;
m_inArgs = methodCall.InArgs;
count = m_inArgs.Length;
m_inArgsNames = new string[ count ];
for( int x = 0; x < count; x++ )
{
m_inArgsNames[ x ] = methodCall.GetInArgName( x );
}
}
if( message is IMethodReturnMessage )
{
IMethodReturnMessage returnMessage = (IMethodReturnMessage) message;
m_outArgs = returnMessage.OutArgs;
count = m_outArgs.Length;
m_outArgsNames = new string[ count ];
for( int x = 0; x < count; x++ )
{
m_outArgsNames[ x ] = returnMessage.GetOutArgName( x );
}
m_returnValue = returnMessage.ReturnValue;
m_exception = returnMessage.Exception;
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PegasusMethodCall"/> class.
/// </summary>
/// <param name="info">The info.</param>
/// <param name="context">The context.</param>
public PegasusMethodCall( SerializationInfo info, StreamingContext context )
{
// Check Parameters
ParamCode.AssertNotNull( info, "info" );
ParamCode.AssertNotNull( context, "context" );
m_properties = (IDictionary) info.GetValue( "m_properties", typeof( IDictionary ) );
m_args = (object[]) info.GetValue( "m_args", typeof( object[] ) );
m_argsNames = (string[]) info.GetValue( "m_argsNames", typeof( string[] ) );
m_hasVarArgs = info.GetBoolean( "m_hasVarArgs" );
m_inArgs = (object[]) info.GetValue( "m_inArgs", typeof( object[] ) );
m_inArgsNames = (string[]) info.GetValue( "m_inArgsNames", typeof( string[] ) );
m_outArgs = (object[]) info.GetValue( "m_outArgs", typeof( object[] ) );
m_outArgsNames = (string[]) info.GetValue( "m_outArgsNames", typeof( string[] ) );
m_returnValue = info.GetValue( "m_returnValue", typeof( object ) );
m_exception = (Exception) info.GetValue( "m_exception", typeof( Exception ) );
m_logicalCallContext = (LogicalCallContext) info.GetValue( "m_logicalCallContext", typeof( LogicalCallContext ) );
m_methodUri = info.GetString( "m_methodUri" );
string methodName = info.GetString( "MethodName" );
string typeName = info.GetString( "TypeName" );
string assemblyName = info.GetString( "AssemblyName" );
// Find the method info object using the version independant binder
Type methodType = s_binder.BindToType( assemblyName, typeName );
if( methodType == null )
{
throw new SerializationException( string.Format( "Unable to find type {0} or assembly {1}", typeName, assemblyName ) );
}
m_methodInfo = methodType.GetMethod( methodName );
if( m_methodInfo == null )
{
throw new SerializationException( string.Format( "Unable to find method {0} in type {1}", methodName, typeName ) );
}
}
/// <summary>
/// Gets an <see cref="T:System.Collections.IDictionary"></see> that represents a collection of the message's properties.
/// </summary>
/// <value></value>
/// <returns>A dictionary that represents a collection of the message's properties.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public IDictionary Properties
{
get
{
return m_properties;
}
}
/// <summary>
/// Gets the number of arguments in the call that are not marked as out parameters.
/// </summary>
/// <value></value>
/// <returns>The number of arguments in the call that are not marked as out parameters.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public int InArgCount
{
get
{
return m_inArgs.Length;
}
}
/// <summary>
/// Gets an array of arguments that are not marked as out parameters.
/// </summary>
/// <value></value>
/// <returns>An array of arguments that are not marked as out parameters.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public object[] InArgs
{
get
{
return m_inArgs;
}
}
/// <summary>
/// Gets the number of arguments passed to the method.
/// </summary>
/// <value></value>
/// <returns>The number of arguments passed to the method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public int ArgCount
{
get
{
return m_args.Length;
}
}
/// <summary>
/// Gets an array of arguments passed to the method.
/// </summary>
/// <value></value>
/// <returns>An <see cref="T:System.Object"></see> array containing the arguments passed to the method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public object[] Args
{
get
{
return m_args;
}
}
/// <summary>
/// Gets a value indicating whether the message has variable arguments.
/// </summary>
/// <value></value>
/// <returns>true if the method can accept a variable number of arguments; otherwise, false.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public bool HasVarArgs
{
get
{
return m_hasVarArgs;
}
}
/// <summary>
/// Gets the <see cref="T:System.Runtime.Remoting.Messaging.LogicalCallContext"></see> for the current method call.
/// </summary>
/// <value></value>
/// <returns>Gets the <see cref="T:System.Runtime.Remoting.Messaging.LogicalCallContext"></see> for the current method call.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public LogicalCallContext LogicalCallContext
{
get
{
return m_logicalCallContext;
}
}
/// <summary>
/// Gets the <see cref="T:System.Reflection.MethodBase"></see> of the called method.
/// </summary>
/// <value></value>
/// <returns>The <see cref="T:System.Reflection.MethodBase"></see> of the called method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public MethodBase MethodBase
{
get
{
return m_methodInfo;
}
}
/// <summary>
/// Gets the name of the invoked method.
/// </summary>
/// <value></value>
/// <returns>The name of the invoked method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public string MethodName
{
get
{
return m_methodInfo.Name;
}
}
/// <summary>
/// Gets an object containing the method signature.
/// </summary>
/// <value></value>
/// <returns>An object containing the method signature.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public object MethodSignature
{
get
{
ParameterInfo[] paramArray = m_methodInfo.GetParameters();
int count = paramArray.Length;
Type[] types = new Type[ count ];
for( int x = 0; x < count; x++ )
{
types[ x ] = paramArray[ x ].ParameterType;
}
return types;
}
}
/// <summary>
/// Gets the full <see cref="T:System.Type"></see> name of the specific object that the call is destined for.
/// </summary>
/// <value></value>
/// <returns>The full <see cref="T:System.Type"></see> name of the specific object that the call is destined for.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public string TypeName
{
get
{
return m_methodInfo.DeclaringType.FullName;
}
}
/// <summary>
/// Gets the URI of the specific object that the call is destined for.
/// </summary>
/// <value></value>
/// <returns>The URI of the remote object that contains the invoked method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public string Uri
{
get
{
return m_methodUri;
}
}
/// <summary>
/// Gets the number of arguments in the method call marked as ref or out parameters.
/// </summary>
/// <value></value>
/// <returns>The number of arguments in the method call marked as ref or out parameters.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public int OutArgCount
{
get
{
return m_outArgs.Length;
}
}
/// <summary>
/// Returns the specified argument marked as a ref or an out parameter.
/// </summary>
/// <value></value>
/// <returns>The specified argument marked as a ref or an out parameter.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public object[] OutArgs
{
get
{
return m_outArgs;
}
}
/// <summary>
/// Gets the return value of the method call.
/// </summary>
/// <value></value>
/// <returns>The return value of the method call.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public object ReturnValue
{
get
{
return m_returnValue;
}
}
/// <summary>
/// Gets the exception thrown during the method call.
/// </summary>
/// <value></value>
/// <returns>The exception object for the method call, or null if the method did not throw an exception.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
public Exception Exception
{
get
{
return m_exception;
}
}
/// <summary>
/// Returns the specified argument that is not marked as an out parameter.
/// </summary>
/// <param name="argNum">The number of the requested in argument.</param>
/// <returns>
/// The requested argument that is not marked as an out parameter.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public object GetInArg( int argNum )
{
// Check Parameters
ParamCode.AssertRange( argNum, 0, m_inArgs.Length - 1, "argNum" );
return m_inArgs[ argNum ];
}
/// <summary>
/// Returns the name of the specified argument that is not marked as an out parameter.
/// </summary>
/// <param name="index">The number of the requested in argument.</param>
/// <returns>
/// The name of a specific argument that is not marked as an out parameter.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public string GetInArgName( int index )
{
// Check Parameters
ParamCode.AssertRange( index, 0, m_inArgsNames.Length - 1, "index" );
return m_inArgsNames[ index ];
}
/// <summary>
/// Gets a specific argument as an <see cref="T:System.Object"></see>.
/// </summary>
/// <param name="argNum">The number of the requested argument.</param>
/// <returns>The argument passed to the method.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public object GetArg( int argNum )
{
// Check Parameters
ParamCode.AssertRange( argNum, 0, m_args.Length - 1, "argNum" );
return m_args[ argNum ];
}
/// <summary>
/// Gets the name of the argument passed to the method.
/// </summary>
/// <param name="index">The number of the requested argument.</param>
/// <returns>
/// The name of the specified argument passed to the method, or null if the current method is not implemented.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public string GetArgName( int index )
{
// Check Parameters
ParamCode.AssertRange( index, 0, m_argsNames.Length - 1, "index" );
return m_argsNames[ index ];
}
/// <summary>
/// Returns the specified argument marked as a ref or an out parameter.
/// </summary>
/// <param name="argNum">The number of the requested argument.</param>
/// <returns>
/// The specified argument marked as a ref or an out parameter.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public object GetOutArg( int argNum )
{
// Check Parameters
ParamCode.AssertRange( argNum, 0, m_outArgs.Length - 1, "argNum" );
return m_outArgs[ argNum ];
}
/// <summary>
/// Returns the name of the specified argument marked as a ref or an out parameter.
/// </summary>
/// <param name="index">The number of the requested argument name.</param>
/// <returns>
/// The argument name, or null if the current method is not implemented.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
public string GetOutArgName( int index )
{
// Check Parameters
ParamCode.AssertRange( index, 0, m_outArgsNames.Length - 1, "index" );
return m_outArgsNames[ index ];
}
/// <summary>
/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> to populate with data.</param>
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"></see>) for this serialization.</param>
/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public void GetObjectData( SerializationInfo info, StreamingContext context )
{
// Check Parameters
ParamCode.AssertNotNull( info, "info" );
ParamCode.AssertNotNull( context, "context" );
info.AddValue( "m_properties", m_properties );
info.AddValue( "m_args", m_args );
info.AddValue( "m_argsNames", m_argsNames );
info.AddValue( "m_hasVarArgs", m_hasVarArgs );
info.AddValue( "m_inArgs", m_inArgs );
info.AddValue( "m_inArgsNames", m_inArgsNames );
info.AddValue( "m_outArgs", m_outArgs );
info.AddValue( "m_outArgsNames", m_outArgsNames );
info.AddValue( "m_returnValue", m_returnValue );
info.AddValue( "m_exception", m_exception );
info.AddValue( "m_logicalCallContext", m_logicalCallContext );
info.AddValue( "m_methodUri", m_methodUri );
// Save the method info data
info.AddValue( "MethodName", m_methodInfo.Name );
info.AddValue( "TypeName", m_methodInfo.DeclaringType.FullName );
info.AddValue( "AssemblyName", m_methodInfo.DeclaringType.Assembly.FullName );
}
}
}