/// <summary>
        /// Registers a service implementation with the RpcServer, it will be used to process received calls.
        /// </summary>
        /// <typeparam name="TService">
        /// The type of the service can be specified explicitly, this allows the name of the service to be discovered
        /// even when the type does not have attributes.
        /// </typeparam>
        /// <param name="service"></param>
        public void RegisterService <TService>(TService service)
        {
            var rpcService = new RpcServiceDescriptor(typeof(TService));

            if (services.ContainsKey(rpcService.Name))
            {
                throw new ArgumentException(String.Format("A service with name '{0}' has already been registered",
                                                          rpcService.Name));
            }

            var serviceInstance = new ServiceInstance {
                Descriptor = rpcService, Instance = service
            };

            foreach (var method in rpcService.Methods)
            {
                serviceInstance.MethodThunks.Add(method.Name, (MethodDelegate)ServiceThunkBuilder.BuildThunk(method));
            }

            services.Add(rpcService.Name, serviceInstance);
        }
Esempio n. 2
0
        public Type Build(Type serviceType)
        {
            if (!serviceType.IsInterface)
            {
                throw new ArgumentException(String.Format(
                                                "Type '{0}' being used to create a proxy must be an interface", serviceType.FullName));
            }

            var service = new RpcServiceDescriptor(serviceType);

            TypeBuilder tb = moduleBuilder.DefineType(serviceType.Name + "Proxy", TypeAttributes.Public,
                                                      typeof(Proxy), new[] { serviceType });

            ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
                                                           new[] { typeof(RpcClient) });

            ILGenerator ctorIlGen = ctor.GetILGenerator();

            ctorIlGen.Emit(OpCodes.Ldarg_0);
            ctorIlGen.Emit(OpCodes.Ldarg_1);
            ctorIlGen.Emit(OpCodes.Ldstr, service.Name);
            ctorIlGen.Emit(OpCodes.Call, typeof(Proxy).GetConstructor(new[] { typeof(RpcClient), typeof(string) }));
            ctorIlGen.Emit(OpCodes.Ret);

            foreach (var method in service.Methods)
            {
                MethodBuilder mb = tb.DefineMethod(method.SyncCallMethod.Name,
                                                   MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, method.ParameterTypes);

                ILGenerator methodIlGen = mb.GetILGenerator();
                methodIlGen.Emit(OpCodes.Ldarg_0);
                methodIlGen.Emit(OpCodes.Ldstr, method.Name);
                EmitParameters(methodIlGen, method.ParameterTypes);
                if (method.ReturnType == typeof(void))
                {
                    methodIlGen.Emit(OpCodes.Call, callWithoutResultHelperMethodInfo);
                }
                else
                {
                    methodIlGen.Emit(OpCodes.Call, blockingCallHelperMethodInfo);
                    EmitReturn(methodIlGen, method.ReturnType);
                }
                methodIlGen.Emit(OpCodes.Ret);

                if (method.HasAsyncDeclarations)
                {
                    MethodBuilder mbBegin = tb.DefineMethod(method.AsyncBeginCallMethod.Name,
                                                            MethodAttributes.Public | MethodAttributes.Virtual, typeof(IAsyncResult),
                                                            method.ParameterTypes.Concat(new[] { typeof(AsyncCallback), typeof(object) }).ToArray());

                    ILGenerator beginIlGen = mbBegin.GetILGenerator();
                    beginIlGen.Emit(OpCodes.Ldarg_0);
                    beginIlGen.Emit(OpCodes.Ldstr, method.Name);
                    EmitParameters(beginIlGen, method.ParameterTypes);
                    beginIlGen.Emit(OpCodes.Ldarg, (short)(method.ParameterTypes.Length + 1)); //callback
                    beginIlGen.Emit(OpCodes.Ldarg, (short)(method.ParameterTypes.Length + 2)); //state
                    beginIlGen.Emit(OpCodes.Call, beginAsyncCallHelperMethodInfo);
                    beginIlGen.Emit(OpCodes.Ret);

                    MethodBuilder mbEnd = tb.DefineMethod(method.AsyncEndCallMethod.Name,
                                                          MethodAttributes.Public | MethodAttributes.Virtual,
                                                          method.ReturnType, new[] { typeof(IAsyncResult) });

                    ILGenerator endIlGen = mbEnd.GetILGenerator();
                    endIlGen.Emit(OpCodes.Ldarg_0);
                    endIlGen.Emit(OpCodes.Ldstr, method.Name);
                    endIlGen.Emit(OpCodes.Ldarg_1);
                    endIlGen.Emit(OpCodes.Call, endAsyncCallHelperMethodInfo);
                    if (method.ReturnType == typeof(void))
                    {
                        endIlGen.Emit(OpCodes.Pop);
                    }
                    else
                    {
                        EmitReturn(endIlGen, method.ReturnType);
                    }
                    endIlGen.Emit(OpCodes.Ret);
                }
            }

            return(tb.CreateType());
        }
Esempio n. 3
0
        public Type Build(Type serviceType)
        {
            if (!serviceType.IsInterface)
                throw new ArgumentException(String.Format(
                    "Type '{0}' being used to create a proxy must be an interface", serviceType.FullName));

            var service = new RpcServiceDescriptor(serviceType);

            TypeBuilder tb = moduleBuilder.DefineType(serviceType.Name + "Proxy", TypeAttributes.Public,
                typeof(Proxy), new[] { serviceType });

            ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
                new[] { typeof(RpcClient) });

            ILGenerator ctorIlGen = ctor.GetILGenerator();
            ctorIlGen.Emit(OpCodes.Ldarg_0);
            ctorIlGen.Emit(OpCodes.Ldarg_1);
            ctorIlGen.Emit(OpCodes.Ldstr, service.Name);
            ctorIlGen.Emit(OpCodes.Call, typeof(Proxy).GetConstructor(new[] { typeof(RpcClient), typeof(string) }));
            ctorIlGen.Emit(OpCodes.Ret);

            foreach (var method in service.Methods)
            {
                MethodBuilder mb = tb.DefineMethod(method.SyncCallMethod.Name,
                    MethodAttributes.Public|MethodAttributes.Virtual, method.ReturnType, method.ParameterTypes);

                ILGenerator methodIlGen = mb.GetILGenerator();
                methodIlGen.Emit(OpCodes.Ldarg_0);
                methodIlGen.Emit(OpCodes.Ldstr, method.Name);
                EmitParameters(methodIlGen, method.ParameterTypes);
                if (method.ReturnType == typeof(void))
                {
                    methodIlGen.Emit(OpCodes.Call, callWithoutResultHelperMethodInfo);
                }
                else
                {
                    methodIlGen.Emit(OpCodes.Call, blockingCallHelperMethodInfo);
                    EmitReturn(methodIlGen, method.ReturnType);
                }
                methodIlGen.Emit(OpCodes.Ret);

                if (method.HasAsyncDeclarations)
                {
                    MethodBuilder mbBegin = tb.DefineMethod(method.AsyncBeginCallMethod.Name,
                        MethodAttributes.Public|MethodAttributes.Virtual, typeof(IAsyncResult),
                        method.ParameterTypes.Concat(new[] { typeof(AsyncCallback), typeof(object) }).ToArray());

                    ILGenerator beginIlGen = mbBegin.GetILGenerator();
                    beginIlGen.Emit(OpCodes.Ldarg_0);
                    beginIlGen.Emit(OpCodes.Ldstr, method.Name);
                    EmitParameters(beginIlGen, method.ParameterTypes);
                    beginIlGen.Emit(OpCodes.Ldarg, (short)(method.ParameterTypes.Length + 1)); //callback
                    beginIlGen.Emit(OpCodes.Ldarg, (short)(method.ParameterTypes.Length + 2)); //state
                    beginIlGen.Emit(OpCodes.Call, beginAsyncCallHelperMethodInfo);
                    beginIlGen.Emit(OpCodes.Ret);

                    MethodBuilder mbEnd = tb.DefineMethod(method.AsyncEndCallMethod.Name,
                        MethodAttributes.Public|MethodAttributes.Virtual,
                        method.ReturnType, new[] { typeof(IAsyncResult) });

                    ILGenerator endIlGen = mbEnd.GetILGenerator();
                    endIlGen.Emit(OpCodes.Ldarg_0);
                    endIlGen.Emit(OpCodes.Ldstr, method.Name);
                    endIlGen.Emit(OpCodes.Ldarg_1);
                    endIlGen.Emit(OpCodes.Call, endAsyncCallHelperMethodInfo);
                    if (method.ReturnType == typeof(void))
                        endIlGen.Emit(OpCodes.Pop);
                    else
                        EmitReturn(endIlGen, method.ReturnType);
                    endIlGen.Emit(OpCodes.Ret);
                }
            }

            return tb.CreateType();
        }