Skip to content

Commit

Permalink
Fix #469 - Unified Messages with LINQ Expressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
yaakov-h committed Oct 14, 2017
1 parent d884c38 commit dd0d0f8
Showing 1 changed file with 26 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ internal UnifiedService( SteamUnifiedMessages steamUnifiedMessages )
/// <returns>The JobID of the request. This can be used to find the appropriate <see cref="ServiceMethodResponse"/>.</returns>
public AsyncJob<ServiceMethodResponse> SendMessage<TResponse>( Expression<Func<TService, TResponse>> expr, bool isNotification = false )
{
// This also doubles as a null check.
if ( !( (object)expr is MethodCallExpression call ) )
if ( expr == null )
{
throw new ArgumentException( "Expression must be a method call expression.", nameof(expr) );
throw new ArgumentNullException( nameof(expr) );
}

var call = ExtractMethodCallExpression( expr, nameof(expr) );
var methodInfo = call.Method;

var argument = call.Arguments.Single();
Expand All @@ -72,9 +72,30 @@ public AsyncJob<ServiceMethodResponse> SendMessage<TResponse>( Expression<Func<T

var rpcName = string.Format( "{0}.{1}#{2}", serviceName, methodName, version );

var method = typeof(SteamUnifiedMessages).GetMethod( "SendMessage" ).MakeGenericMethod( message.GetType() );
var method = typeof(SteamUnifiedMessages).GetMethod( nameof(SteamUnifiedMessages.SendMessage) ).MakeGenericMethod( message.GetType() );
var result = method.Invoke( this.steamUnifiedMessages, new[] { rpcName, message, isNotification } );
return (AsyncJob<ServiceMethodResponse>)result;
return ( AsyncJob<ServiceMethodResponse> )result;
}

static MethodCallExpression ExtractMethodCallExpression<TResponse>( Expression<Func<TService, TResponse>> expression, string paramName )
{
switch ( expression.NodeType )
{
// Older code/tests/whatever were compiled down to just a single MethodCallExpression.
case ExpressionType.Call:
return ( MethodCallExpression )expression.Body;

// Newer code/tests/whatever are now compiled by wrapping the MethodCallExpression in a LambdaExpression.
case ExpressionType.Lambda:
if ( expression.Body.NodeType == ExpressionType.Call )
{
var lambda = ( LambdaExpression )expression;
return ( MethodCallExpression )lambda.Body;
}
break;
}

throw new ArgumentException( "Expression must be a method call.", paramName );
}
}

Expand Down

0 comments on commit dd0d0f8

Please sign in to comment.