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 );
		}
Esempio n. 5
0
		/// <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();
		}
Esempio n. 6
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 );
		}
Esempio n. 7
0
		/// <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();
				}
			}
		}
Esempio n. 8
0
		/// <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 );
		}
Esempio n. 9
0
		/// <summary>
		///		Initializes a new instance of the <see cref="AsyncServiceInvoker&lt;T&gt;"/> 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 ) );
		}
Esempio n. 15
0
		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 );
		}
Esempio n. 17
0
		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 );
		}