public void TestConstructor_NameIsEmpty_Ok() { string name = String.Empty; Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); Assert.That( target.Name, Is.Not.Null.And.Length.EqualTo( 0 ) ); }
public void TestConstructor_NameContainsNonAsciiLetter() { string name = "\u30C6\u30B9\u30C8"; Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); Assert.That( target.Name, Is.EqualTo( name ) ); }
public void TestConstructor_Normal_PropertiesAreAllSet() { var name = "Name" + Guid.NewGuid().ToString( "N" ); Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); Assert.That( target.Initializer, Is.EqualTo( initializer ) ); Assert.That( target.Name, Is.EqualTo( name ) ); Assert.That( target.ServiceType, Is.EqualTo( initializer.Method.DeclaringType ) ); Assert.That( target.Version, Is.EqualTo( 0 ) ); }
public void TestEquals_NameAreDiffer_VersionAreSame_TypeAreSame_False() { var left = new ServiceDescription( "TestA", () => new object() ) { Version = 1 }; var right = new ServiceDescription( "TestB", () => new object() ) { Version = 1 }; Assert.That( left.Equals( right ), Is.False ); }
/// <summary> /// Creates the collection of the <see cref="OperationDescription"/> from the service description. /// </summary> /// <param name="runtime">The <see cref="RpcServerRuntime"/> which provides runtime services.</param> /// <param name="service">The target service description.</param> /// <returns> /// Collection of the <see cref="OperationDescription"/> from the service description. /// This value will not be <c>null</c> but might be empty. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="runtime"/> is <c>null</c>. /// Or, <paramref name="service"/> is <c>null</c>. /// </exception> public static IEnumerable<OperationDescription> FromServiceDescription( RpcServerRuntime runtime, ServiceDescription service ) { if ( runtime == null ) { throw new ArgumentNullException( "runtime" ); } if ( service == null ) { throw new ArgumentNullException( "service" ); } Contract.Ensures( Contract.Result<IEnumerable<OperationDescription>>() != null ); Contract.Ensures( Contract.ForAll( Contract.Result<IEnumerable<OperationDescription>>(), item => item != null ) ); var generated = new HashSet<string>(); return service.ServiceType.GetMethods() .Where( method => method.DeclaringType != objectType && !method.IsDefined( typeof(NoActionAttribute), true ) ) .Select( operation => { if ( !generated.Add( operation.Name ) ) { throw new NotSupportedException( String.Format( CultureInfo.CurrentCulture, "Method '{0}' is overloaded. Method overload is not supported on the MessagePack-RPC.", operation.Name ) ); } return FromServiceMethodCore( runtime, service, operation ); } ).ToArray(); }
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 ); }
/// <summary> /// Gets service invoker. /// If the concrete type is already created, returns the cached instance. /// Else creates new concrete type and its instance, then returns it. /// </summary> /// <param name="runtime"> /// The <see cref="RpcServerRuntime"/>. /// </param> /// <param name="serviceDescription"> /// <see cref="ServiceDescription"/> which holds the service spec. /// </param> /// <param name="targetOperation"> /// <see cref="MethodInfo"/> of the target operation. /// </param> /// <returns> /// <see cref="AsyncServiceInvoker{T}"/> where T is return type of the target method. /// </returns> public IAsyncServiceInvoker GetServiceInvoker( RpcServerRuntime runtime, ServiceDescription serviceDescription, MethodInfo targetOperation ) { Contract.Requires( runtime != null ); Contract.Requires( serviceDescription != null ); Contract.Requires( targetOperation != null ); bool isReadLockHeld = false; try { try { } finally { this._lock.EnterUpgradeableReadLock(); isReadLockHeld = true; } IAsyncServiceInvoker result; if ( this._cache.TryGetValue( targetOperation.MethodHandle, out result ) ) { return result; } IAsyncServiceInvoker newInvoker = CreateInvoker( runtime, serviceDescription, targetOperation ); bool isWriteLockHeld = false; try { try { } finally { this._lock.EnterWriteLock(); isWriteLockHeld = true; } if ( !this._cache.TryGetValue( targetOperation.MethodHandle, out result ) ) { this._cache[ targetOperation.MethodHandle ] = newInvoker; result = newInvoker; } return result; } finally { if ( isWriteLockHeld ) { this._lock.ExitWriteLock(); } } } finally { if ( isReadLockHeld ) { this._lock.ExitUpgradeableReadLock(); } } }
/// <summary> /// Creates the invoke type built now and returns its new instance. /// </summary> /// <param name="runtime">The <see cref="RpcServerRuntime"/> which provides runtime services.</param> /// <param name="serviceDescription">The <see cref="ServiceDescription"/> which holds the service spec.</param> /// <param name="targetOperation">The <see cref="MethodInfo"/> which holds the operation method spec.</param> /// <returns> /// Newly built <see cref="IAsyncServiceInvoker"/> instance. /// This value will not be <c>null</c>. /// </returns> public IAsyncServiceInvoker CreateInstance( RpcServerRuntime runtime, ServiceDescription serviceDescription, MethodInfo targetOperation ) { var runtimeParameter = Expression.Parameter( typeof( RpcServerRuntime ) ); var serviceDescriptionParameter = Expression.Parameter( typeof( ServiceDescription ) ); var targetOperationParameter = Expression.Parameter( typeof( MethodInfo ) ); return Expression.Lambda<Func<RpcServerRuntime, ServiceDescription, MethodInfo, IAsyncServiceInvoker>>( Expression.New( this.Create(), runtimeParameter, serviceDescriptionParameter, targetOperationParameter ), runtimeParameter, serviceDescriptionParameter, targetOperationParameter ).Compile()( runtime, serviceDescription, targetOperation ); }
/// <summary> /// Initializes a new instance of the <see cref="AsyncServiceInvoker<T>"/> class. /// </summary> /// <param name="runtime">The <see cref="RpcServerRuntime"/> which provides runtime services.</param> /// <param name="serviceDescription">The service description which defines target operation.</param> /// <param name="targetOperation">The target operation to be invoked.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="runtime"/> is <c>null</c>. /// Or, <paramref name="serviceDescription"/> is <c>null</c>. /// Or, <paramref name="targetOperation"/> is <c>null</c>. /// </exception> internal AsyncServiceInvoker( RpcServerRuntime runtime, ServiceDescription serviceDescription, MethodInfo targetOperation ) { if ( runtime == null ) { throw new ArgumentNullException( "runtime" ); } if ( serviceDescription == null ) { throw new ArgumentNullException( "serviceDescription" ); } if ( targetOperation == null ) { throw new ArgumentNullException( "targetOperation" ); } Contract.EndContractBlock(); this._runtime = runtime; this._serviceDescription = serviceDescription; this._targetOperation = targetOperation; this._operationId = ServiceIdentifier.TruncateGenericsSuffix( targetOperation.Name ); }
public void TestGetHashCode_VersionIsSet_Harmless() { var name = "Name" + Guid.NewGuid().ToString( "N" ); Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ) { Version = 123 }; // Test it does not throw any exceptions. target.GetHashCode(); }
public void TestConstructor_NameContainsSymbol() { // It might be natural in some environemnt but they should not be used. // We should follow UAX-31 to maximize interoperability. string name = "Test?"; Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); }
public void TestConstructor_NameIsBlank() { string name = " "; Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); }
public void TestToString_VersionIsNotSet_Omitted() { var name = "Name" + Guid.NewGuid().ToString( "N" ); Func<Object> initializer = () => new object(); ServiceDescription target = new ServiceDescription( name, initializer ); var result = target.ToString(); Assert.That( Regex.Matches( result, Regex.Escape( name ) ), Is.Not.Null.And.Count.EqualTo( 1 ) ); }
public void TestToString_VersionIsSet_Appeared() { var name = "Name" + Guid.NewGuid().ToString( "N" ); Func<Object> initializer = () => new object(); var version = DateTime.UtcNow.Millisecond; ServiceDescription target = new ServiceDescription( name, initializer ) { Version = version }; var result = target.ToString(); Assert.That( Regex.Matches( result, Regex.Escape( name ) ), Is.Not.Null.And.Count.EqualTo( 1 ) ); Assert.That( Regex.Matches( result, Regex.Escape( ":" + version ) ), Is.Not.Null.And.Count.EqualTo( 1 ) ); }
private static OperationDescription FromServiceMethodCore( RpcServerRuntime runtime, ServiceDescription service, MethodInfo operation ) { Contract.Requires( runtime != null ); Contract.Ensures( Contract.Result<OperationDescription>() != null ); var serviceInvoker = ServiceInvokerGenerator.Default.GetServiceInvoker( runtime, service, operation ); return new OperationDescription( service, serviceInvoker.OperationId, serviceInvoker.InvokeAsync ); }
public void TestConstructor_InitializerIsNull() { var name = "Name" + Guid.NewGuid().ToString( "N" ); Func<Object> initializer = null; ServiceDescription target = new ServiceDescription( name, initializer ); }
private OperationDescription( ServiceDescription service, string id, Func<ServerRequestContext, ServerResponseContext, Task> operation ) { Validation.ValidateMethodName( id, "id" ); Contract.EndContractBlock(); this._service = service; this._operation = operation; this._id = id; }
private static OperationDescription CreateOperation( string methodName, string scope, int version ) { var serviceDescription = new ServiceDescription( scope, () => null ); serviceDescription.Version = version; var id = methodName; Func<ServerRequestContext, ServerResponseContext, Task> operation = ( _0, _1 ) => null; return _operationDescriptionConstructor( serviceDescription, id, operation ); }