private IAsyncServiceInvoker CreateInvoker(RpcServerRuntime runtime, ServiceDescription serviceDescription, MethodInfo targetOperation)
        {
            var parameters = targetOperation.GetParameters();

            CheckParameters(parameters);
            bool isWrapperNeeded = !typeof(Task).IsAssignableFrom(targetOperation.ReturnType);

            var emitter = new ServiceInvokerEmitter(this._moduleBuilder, Interlocked.Increment(ref this._typeSequence), targetOperation.DeclaringType, targetOperation.ReturnType, this._isDebuggable);

            EmitInvokeCore(emitter, targetOperation, parameters, typeof(Task), isWrapperNeeded);

            return(emitter.CreateInstance(runtime, serviceDescription, targetOperation));
        }
        private static void EmitWrapperInvocation(ServiceInvokerEmitter emitter, TracingILGenerator il, LocalBuilder service, MethodInfo targetOperation, LocalBuilder[] unpackedArguments)
        {
            /*
             * returnValue = Task.Factory.StartNew( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) );
             */
            var itemTypes  = Enumerable.Repeat(service, 1).Concat(unpackedArguments).Select(item => item.LocalType).ToArray();
            var tupleTypes = TupleItems.CreateTupleTypeList(itemTypes);

            EmitPrivateInvoke(emitter.GetPrivateInvokeMethodILGenerator(targetOperation.ReturnType), targetOperation, tupleTypes, itemTypes);

            il.EmitGetProperty(_taskFactoryProperty);

            // new DELEGATE( PrivateInvoke ) ->new DELGATE( null, funcof( PrivateInvoke ) )
            il.EmitLdarg_0();
            il.EmitLdftn(emitter.PrivateInvokeMethod);
            il.EmitNewobj(
                targetOperation.ReturnType == typeof(void)
                                ? typeof(Action <object>).GetConstructor(_delegateConstructorParameterTypes)
                                : typeof(Func <,>).MakeGenericType(typeof(object), targetOperation.ReturnType).GetConstructor(_delegateConstructorParameterTypes)
                );

            il.EmitAnyLdloc(service);

            foreach (var item in unpackedArguments)
            {
                il.EmitAnyLdloc(item);
            }

            foreach (var tupleType in tupleTypes)
            {
                il.EmitNewobj(tupleType.GetConstructors().Single());
            }

            if (targetOperation.ReturnType == typeof(void))
            {
                il.EmitAnyCall(_taskFactoryStartNew_Action_1_Object_Object);
            }
            else
            {
                il.EmitAnyCall(_taskFactoryStartNew_Func_1_Object_T_Object.MakeGenericMethod(targetOperation.ReturnType));
            }
        }
Exemplo n.º 3
0
		private static void EmitWrapperInvocation( ServiceInvokerEmitter emitter, TracingILGenerator il, LocalBuilder service, MethodInfo targetOperation, LocalBuilder[] unpackedArguments )
		{
			/*
			 * returnValue = Task.Factory.StartNew( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) );
			 */
			var itemTypes = Enumerable.Repeat( service, 1 ).Concat( unpackedArguments ).Select( item => item.LocalType ).ToArray();
			var tupleTypes = TupleItems.CreateTupleTypeList( itemTypes );
			EmitPrivateInvoke( emitter.GetPrivateInvokeMethodILGenerator( targetOperation.ReturnType ), targetOperation, tupleTypes, itemTypes );

			il.EmitGetProperty( _taskFactoryProperty );

			// new DELEGATE( PrivateInvoke ) ->new DELGATE( null, funcof( PrivateInvoke ) )
			il.EmitLdarg_0();
			il.EmitLdftn( emitter.PrivateInvokeMethod );
			il.EmitNewobj(
				targetOperation.ReturnType == typeof( void )
				? typeof( Action<object> ).GetConstructor( _delegateConstructorParameterTypes )
				: typeof( Func<,> ).MakeGenericType( typeof( object ), targetOperation.ReturnType ).GetConstructor( _delegateConstructorParameterTypes )
			);

			il.EmitAnyLdloc( service );

			foreach ( var item in unpackedArguments )
			{
				il.EmitAnyLdloc( item );
			}

			foreach ( var tupleType in tupleTypes )
			{
				il.EmitNewobj( tupleType.GetConstructors().Single() );
			}

			if ( targetOperation.ReturnType == typeof( void ) )
			{
				il.EmitAnyCall( _taskFactoryStartNew_Action_1_Object_Object );
			}
			else
			{
				il.EmitAnyCall( _taskFactoryStartNew_Func_1_Object_T_Object.MakeGenericMethod( targetOperation.ReturnType ) );
			}

		}
Exemplo n.º 4
0
		private static void EmitInvokeCore( ServiceInvokerEmitter emitter, MethodInfo targetOperation, ParameterInfo[] parameters, Type returnType, bool isWrapperNeeded )
		{
			var methodReturnType = targetOperation.ReturnType == typeof( void ) ? typeof( Missing ) : targetOperation.ReturnType;
			var asyncInvokerIsDebugModeProperty = typeof( AsyncServiceInvoker<> ).MakeGenericType( methodReturnType ).GetProperty( "IsDebugMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
			var il = emitter.GetInvokeCoreMethodILGenerator();
			try
			{
				var endOfMethod = il.DefineLabel();
				var unpackedArguments = parameters.Select( item => il.DeclareLocal( item.ParameterType, item.Name ) ).ToArray();
				var serializers = unpackedArguments.Select( item => emitter.RegisterSerializer( item.LocalType ) ).ToArray();

				var result = il.DeclareLocal( typeof( AsyncInvocationResult ), "result" );

				/*
				 *	using( var argumentsItemUnpacker = arguments.ReadSubTree() )
				 *	{
				 *		argumentsItemUnpacker.
				 *		...
				 *	}
				 */

				var argumentsItemUnpacker = il.DeclareLocal( typeof( Unpacker ), "argumentsItemUnpacker" );
				il.EmitAnyLdarg( 1 );
				il.EmitAnyCall( _unpackerReadSubtreeMethod );
				il.EmitAnyStloc( argumentsItemUnpacker );
				il.BeginExceptionBlock();

				for ( int i = 0; i < parameters.Length; i++ )
				{
					/*
					 *	if ( !argumentsItemUnpacker.Read() )
					 *	{
					 *		throw new SerializationException( String.Format( CultureInfo.CurrentCuture, "Stream unexpectedly ends at argument {0}.", N ) );
					 *	}
					 *	
					 *	T argN;
					 *	try
					 *	{
					 *		argN = this._serializerN.UnpackFrom( argumentsItemUnpacker );
					 *	}
					 *	catch( Exception ex )
					 *	{
					 *		return new AsyncInvocatonResult( InvocationHelper.HandleArgumentDeserializationException( ex, "argN" ) );
					 *		return;
					 *	}
					 */
					il.EmitAnyLdloc( argumentsItemUnpacker );
					il.EmitAnyCall( _unpackerReadMethod );
					var endIf = il.DefineLabel();
					il.EmitBrtrue_S( endIf );
					var args = il.DeclareLocal( typeof( object[] ), "args" );
					il.EmitNewarr( typeof( object ), 1 );
					il.EmitAnyStloc( args );
					il.EmitGetProperty( _cultureInfoCurrentCultureProperty );

					il.EmitLdstr( "Stream unexpectedly ends at arguments array {0}." );
					il.EmitAnyLdloc( args );
					il.EmitAnyLdc_I4( 0 );
					il.EmitAnyLdc_I4( i );
					il.EmitBox( typeof( int ) );
					il.EmitStelem( typeof( object ) );
					il.EmitAnyLdloc( args );
					il.EmitAnyCall( _stringFormatMethod );
					il.EmitNewobj( _serializationExceptionCtorStringConstructor );
					il.EmitThrow();
					il.MarkLabel( endIf );

					il.BeginExceptionBlock();
					il.EmitAnyLdarg( 0 );
					il.EmitLdfld( serializers[ i ] );
					il.EmitAnyLdloc( argumentsItemUnpacker );
					il.EmitAnyCall( serializers[ i ].FieldType.GetMethod( "UnpackFrom", BindingFlags.Public | BindingFlags.Instance ) );
					il.EmitAnyStloc( unpackedArguments[ i ] );

					EmitExceptionHandling(
						il,
						returnType,
						endOfMethod,
						( il0, exception ) =>
						{
							il0.EmitAnyLdloc( exception );
							il0.EmitLdstr( parameters[ i ].Name );
							il0.EmitAnyLdarg( 0 );
							il0.EmitGetProperty( asyncInvokerIsDebugModeProperty );
							il0.EmitCall( InvocationHelper.HandleArgumentDeserializationExceptionMethod );
							il0.EmitNewobj( _asyncInvocationResultErrorConstructor );
							il0.EmitAnyStloc( result );
						}
					);
				}

				il.BeginFinallyBlock();
				il.EmitAnyLdloc( argumentsItemUnpacker );
				il.EmitAnyCall( _idisposableDisposeMethod );
				il.EndExceptionBlock();

				/*
				 *	TService service = this._serviceDescription.Initializer()
				 */

				var service = il.DeclareLocal( targetOperation.DeclaringType, "service" );
				il.EmitAnyLdarg( 0 );
				il.EmitGetProperty( typeof( AsyncServiceInvoker<> ).MakeGenericType( methodReturnType ).GetProperty( "ServiceDescription" ) );
				il.EmitGetProperty( ServiceDescription.InitializerProperty );
				il.EmitAnyCall( _func_1_Invoke );
				il.EmitCastclass( service.LocalType );
				il.EmitAnyStloc( service );

				/*
				 *	#if IS_TASK
				 *	return new AsyncInvocationResult( service.Target( arg1, ..., argN ) );
				 *	#else
				 *	return new AsyncInvocationResult( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) ) );
				 *	#endif
				 */

				if ( !isWrapperNeeded )
				{
					il.EmitAnyLdloc( service );
					foreach ( var arg in unpackedArguments )
					{
						il.EmitAnyLdloc( arg );
					}

					il.EmitAnyCall( targetOperation );
				}
				else
				{
					EmitWrapperInvocation( emitter, il, service, targetOperation, unpackedArguments );
				}

				il.EmitNewobj( _asyncInvocationResultTaskConstructor );
				il.EmitAnyStloc( result );
				il.MarkLabel( endOfMethod );
				il.EmitAnyLdloc( result );
				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
Exemplo n.º 5
0
		private IAsyncServiceInvoker CreateInvoker( RpcServerRuntime runtime, ServiceDescription serviceDescription, MethodInfo targetOperation )
		{
			var parameters = targetOperation.GetParameters();
			CheckParameters( parameters );
			bool isWrapperNeeded = !typeof( Task ).IsAssignableFrom( targetOperation.ReturnType );

			var emitter = new ServiceInvokerEmitter( this._moduleBuilder, Interlocked.Increment( ref this._typeSequence ), targetOperation.DeclaringType, targetOperation.ReturnType, this._isDebuggable );
			EmitInvokeCore( emitter, targetOperation, parameters, typeof( Task ), isWrapperNeeded );

			return emitter.CreateInstance( runtime, serviceDescription, targetOperation );
		}
        private static void EmitInvokeCore(ServiceInvokerEmitter emitter, MethodInfo targetOperation, ParameterInfo[] parameters, Type returnType, bool isWrapperNeeded)
        {
            var methodReturnType = targetOperation.ReturnType == typeof(void) ? typeof(Missing) : targetOperation.ReturnType;
            var asyncInvokerIsDebugModeProperty = typeof(AsyncServiceInvoker <>).MakeGenericType(methodReturnType).GetProperty("IsDebugMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            var il = emitter.GetInvokeCoreMethodILGenerator();

            try
            {
                var endOfMethod       = il.DefineLabel();
                var unpackedArguments = parameters.Select(item => il.DeclareLocal(item.ParameterType, item.Name)).ToArray();
                var serializers       = unpackedArguments.Select(item => emitter.RegisterSerializer(item.LocalType)).ToArray();

                var result = il.DeclareLocal(typeof(AsyncInvocationResult), "result");

                /*
                 *	using( var argumentsItemUnpacker = arguments.ReadSubTree() )
                 *	{
                 *		argumentsItemUnpacker.
                 *		...
                 *	}
                 */

                var argumentsItemUnpacker = il.DeclareLocal(typeof(Unpacker), "argumentsItemUnpacker");
                il.EmitAnyLdarg(1);
                il.EmitAnyCall(_unpackerReadSubtreeMethod);
                il.EmitAnyStloc(argumentsItemUnpacker);
                il.BeginExceptionBlock();

                for (int i = 0; i < parameters.Length; i++)
                {
                    /*
                     *	if ( !argumentsItemUnpacker.Read() )
                     *	{
                     *		throw new SerializationException( String.Format( CultureInfo.CurrentCuture, "Stream unexpectedly ends at argument {0}.", N ) );
                     *	}
                     *
                     *	T argN;
                     *	try
                     *	{
                     *		argN = this._serializerN.UnpackFrom( argumentsItemUnpacker );
                     *	}
                     *	catch( Exception ex )
                     *	{
                     *		return new AsyncInvocatonResult( InvocationHelper.HandleArgumentDeserializationException( ex, "argN" ) );
                     *		return;
                     *	}
                     */
                    il.EmitAnyLdloc(argumentsItemUnpacker);
                    il.EmitAnyCall(_unpackerReadMethod);
                    var endIf = il.DefineLabel();
                    il.EmitBrtrue_S(endIf);
                    var args = il.DeclareLocal(typeof(object[]), "args");
                    il.EmitNewarr(typeof(object), 1);
                    il.EmitAnyStloc(args);
                    il.EmitGetProperty(_cultureInfoCurrentCultureProperty);

                    il.EmitLdstr("Stream unexpectedly ends at arguments array {0}.");
                    il.EmitAnyLdloc(args);
                    il.EmitAnyLdc_I4(0);
                    il.EmitAnyLdc_I4(i);
                    il.EmitBox(typeof(int));
                    il.EmitStelem(typeof(object));
                    il.EmitAnyLdloc(args);
                    il.EmitAnyCall(_stringFormatMethod);
                    il.EmitNewobj(_serializationExceptionCtorStringConstructor);
                    il.EmitThrow();
                    il.MarkLabel(endIf);

                    il.BeginExceptionBlock();
                    il.EmitAnyLdarg(0);
                    il.EmitLdfld(serializers[i]);
                    il.EmitAnyLdloc(argumentsItemUnpacker);
                    il.EmitAnyCall(serializers[i].FieldType.GetMethod("UnpackFrom", BindingFlags.Public | BindingFlags.Instance));
                    il.EmitAnyStloc(unpackedArguments[i]);

                    EmitExceptionHandling(
                        il,
                        returnType,
                        endOfMethod,
                        (il0, exception) =>
                    {
                        il0.EmitAnyLdloc(exception);
                        il0.EmitLdstr(parameters[i].Name);
                        il0.EmitAnyLdarg(0);
                        il0.EmitGetProperty(asyncInvokerIsDebugModeProperty);
                        il0.EmitCall(InvocationHelper.HandleArgumentDeserializationExceptionMethod);
                        il0.EmitNewobj(_asyncInvocationResultErrorConstructor);
                        il0.EmitAnyStloc(result);
                    }
                        );
                }

                il.BeginFinallyBlock();
                il.EmitAnyLdloc(argumentsItemUnpacker);
                il.EmitAnyCall(_idisposableDisposeMethod);
                il.EndExceptionBlock();

                /*
                 *	TService service = this._serviceDescription.Initializer()
                 */

                var service = il.DeclareLocal(targetOperation.DeclaringType, "service");
                il.EmitAnyLdarg(0);
                il.EmitGetProperty(typeof(AsyncServiceInvoker <>).MakeGenericType(methodReturnType).GetProperty("ServiceDescription"));
                il.EmitGetProperty(ServiceDescription.InitializerProperty);
                il.EmitAnyCall(_func_1_Invoke);
                il.EmitCastclass(service.LocalType);
                il.EmitAnyStloc(service);

                /*
                 *	#if IS_TASK
                 *	return new AsyncInvocationResult( service.Target( arg1, ..., argN ) );
                 *	#else
                 *	return new AsyncInvocationResult( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) ) );
                 *	#endif
                 */

                if (!isWrapperNeeded)
                {
                    il.EmitAnyLdloc(service);
                    foreach (var arg in unpackedArguments)
                    {
                        il.EmitAnyLdloc(arg);
                    }

                    il.EmitAnyCall(targetOperation);
                }
                else
                {
                    EmitWrapperInvocation(emitter, il, service, targetOperation, unpackedArguments);
                }

                il.EmitNewobj(_asyncInvocationResultTaskConstructor);
                il.EmitAnyStloc(result);
                il.MarkLabel(endOfMethod);
                il.EmitAnyLdloc(result);
                il.EmitRet();
            }
            finally
            {
                il.FlushTrace();
            }
        }