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)); } }
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 ) ); } }
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(); } }
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(); } }