public virtual T GetProxyObject <T>(IRpcChannel channel, int remoteInstanceId) { return((T)GetProxyObject( channel, new[] { typeof(T) }.Concat(typeof(T).GetInterfaces()).ToArray(), remoteInstanceId)); }
public override object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId) { lock (_rpcObjects) { Purge(); if (_rpcObjects.TryGetValue(RpcHandle.ComparisonHandle(remoteInstanceId), out var obj)) { if (((RpcObjectHandle)obj).Object.TryGetTarget(out var inst)) { return(inst); } } bool isDelegate = interfaceTypes.Length == 1 && interfaceTypes[0].IsSubclassOf(typeof(Delegate)); var result = new RpcObjectHandle(null, pinned: /*isDelegate && !_clientRepository,*/ false, instanceId: remoteInstanceId); _rpcObjects.Add(result); var instance = isDelegate ? ImplementDelegate(interfaceTypes[0], channel, remoteInstanceId, result.InstanceId) : ImplementInterfaces(interfaceTypes, channel, remoteInstanceId, result.InstanceId); result.Object = new WeakReference <object>(instance); return(instance); } }
/// <summary> /// Gets a proxy to the service instance specified by <paramref name="objectId"/>. /// </summary> /// <typeparam name="TService"></typeparam> /// <param name="objectId"></param> /// <param name="useSyncContext">Indicates that the current synchronization context should be used for the service intance.</param> /// <returns>The service proxy.</returns> /// <exception cref="RpcDefinitionException">Thrown if the RPC definition of <typeparamref name="TService"/> is not correct.</exception> public static TService GetServiceInstance <TService>(this IRpcChannel connection, RpcObjectId objectId, bool useSyncContext = true) where TService : class { if (connection is null) { throw new ArgumentNullException(nameof(connection)); } return(connection.GetServiceInstance <TService>(objectId, default, useSyncContext ? SynchronizationContext.Current : null));
public ClientDispatchProxy(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; m_RpcChannel = serviceProvider.GetRequiredService <IRpcChannel>(); m_RpcChannel.NewPackageReceived += NewPackageReceived; m_RpcCodec = serviceProvider.GetRequiredService <IRpcCodec>(); m_InvokeRepository = serviceProvider.GetRequiredService <IInvokeRepository>(); }
public object DecodeRpcCallResultMessage(IRpcChannel channel, IRpcObjectRepository localRepository, IRpcObjectRepository remoteRepository, IRpcSerializer serializer, RpcCallResultMessage message, Type resultType) { if (message.Type == RpcMessageType.Exception) { throw new TargetInvocationException((Exception)message.Result.Value); } return(DecodeRpcArgument(channel, localRepository, remoteRepository, serializer, message.Result, resultType)); }
public RpcProxyArgs( IRpcChannel connection, RpcObjectId objectId, IRpcSerializer serializer, IReadOnlyCollection <string>?implementedServices, SynchronizationContext?syncContext) { this.Channel = connection ?? throw new ArgumentNullException(nameof(connection)); this.ObjectId = objectId; this.Serializer = serializer; this.ImplementedServices = implementedServices; this.SyncContext = syncContext; }
internal GrpcProxyArgs(IRpcChannel connection, GrpcCore.CallInvoker callInvoker, RpcObjectId objectId, GrpcMethodsCache methodsCache, IRpcSerializer serializer, IReadOnlyCollection <string>?implementedServices, SynchronizationContext?syncContext) : base(connection, objectId, serializer, implementedServices, syncContext) { this.CallInvoker = callInvoker; this.MethodsCache = methodsCache; }
public static TService Create <TService>(IRpcChannel rpcChannel) where TService : class, IRpcService { var serviceType = typeof(TService); if (!_proxyClientCache.ContainsKey(serviceType) || !_proxyClientCache.TryGetValue(serviceType, out var serviceInstanceTypeInfo)) { serviceInstanceTypeInfo = _builder.Create <TService>(); _proxyClientCache.TryAdd(serviceType, serviceInstanceTypeInfo); } var instance = Activator.CreateInstance(serviceInstanceTypeInfo, rpcChannel); return((TService)instance); }
public object DecodeRpcArgument(IRpcChannel channel, IRpcObjectRepository localRepository, IRpcObjectRepository remoteRepository, IRpcSerializer serializer, RpcArgument argument, Type argumentType) { switch (argument.Type) { case RpcType.Builtin: if (argument.Value == null || argumentType == typeof(void)) { return(null); } if (argumentType.IsAssignableFrom(argument.Value.GetType())) { return(argument.Value); } return(serializer.ChangeType(argument.Value, argumentType)); case RpcType.Proxy: var instanceId = (int)serializer.ChangeType(argument.Value, typeof(int)); var instance = localRepository.GetInstance(instanceId); if (instance == null) { var intfTypes = localRepository.ResolveTypes(argument.TypeId, argumentType); instance = remoteRepository.GetProxyObject(channel, intfTypes, instanceId); } return(instance); case RpcType.Serialized: var type = localRepository.ResolveTypes(argument.TypeId, argumentType)[0]; return(serializer.ChangeType(argument.Value, type)); case RpcType.ObjectArray: var arrayType = localRepository.ResolveTypes(argument.TypeId, argumentType)[0]; var elementType = arrayType?.GetElementType() ?? throw new InvalidOperationException(); var array = Array.CreateInstance(elementType, (int)argument.Value); for (int i = 0; i < array.Length; i++) { array.SetValue(DecodeRpcArgument(channel, localRepository, remoteRepository, serializer, argument.ArrayElements[i], elementType), i); } return(array); default: throw new InvalidDataException(); } }
public override object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId) { lock (_rpcObjects) { Purge(); if (_rpcObjects.TryGetValue(RpcHandle.ComparisonHandle(remoteInstanceId), out var obj)) { if (((RpcObjectHandle)obj).Object.TryGetTarget(out var inst)) { return(inst); } } bool isDelegate = interfaceTypes.Length == 1 && interfaceTypes[0].IsSubclassOf(typeof(Delegate)); var result = new RpcObjectHandle(null, pinned: /*isDelegate && !_clientRepository,*/ false, instanceId: remoteInstanceId); _rpcObjects.Add(result); object instance; if (isDelegate) { throw new NotSupportedException("We do not support delegates for now."); } else { var typesHash = CreateTypesHash(interfaceTypes); if (!_typeImplementations.TryGetValue(typesHash, out var implementationType)) { throw new InvalidOperationException($"Implementation type for interfaces {string.Join(", ", interfaceTypes.Select(t => t.ToString()))} not found."); } var constructor = implementationType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(IRpcChannel), typeof(int), typeof(int) }, null); instance = constructor.Invoke(new object[] { channel, result.InstanceId, remoteInstanceId }); } result.Object = new WeakReference <object>(instance); return(instance); } }
public bool RemoveKnownChannel(IRpcChannel channel) { var connectionInfo = channel?.ConnectionInfo; if (connectionInfo == null) { return(false); } bool removed = false; lock (this.syncRoot) { if (connectionInfo.ServerId != RpcServerId.Empty) { if (this.idToKnownConnection.TryGetValue(connectionInfo.ServerId, out var currConnection)) { if (channel == currConnection) { this.idToKnownConnection.Remove(connectionInfo.ServerId); removed = true; } } } if (connectionInfo.HostUrl != null) { if (this.urlToKnownConnection.TryGetValue(connectionInfo.HostUrl, out var currConnection)) { if (channel == currConnection) { this.urlToKnownConnection.Remove(connectionInfo.HostUrl); removed = true; } } } } return(removed); }
private object ImplementDelegate(Type delegateType, IRpcChannel channel, int remoteInstanceId, int localInstanceId) { RpcTypeDefinition type; lock (_proxyImplementations) { var hash = CreateTypesHash(delegateType); if (!_proxyImplementations.TryGetValue(hash, out type)) { var tb = _moduleBuilder.DefineType($"{delegateType.Name}Shadow{Guid.NewGuid():n}"); var invokerField = CreateConstructor(tb); var(localField, remoteField) = ImplementIRpcObjectProxy(tb); CreateDestructor(tb, invokerField, localField, remoteField); ImplementMethod(tb, delegateType.GetMethod("Invoke"), invokerField, remoteField, false); type = new RpcTypeDefinition { Type = tb.CreateTypeInfo().AsType() }; type.LocalIdField = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance); type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance); _proxyImplementations.Add(hash, type); } } var delObj = Activator.CreateInstance(type.Type, channel); Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null"); Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null"); type.LocalIdField.SetValue(delObj, localInstanceId); type.RemoteIdField.SetValue(delObj, remoteInstanceId); return(Delegate.CreateDelegate(delegateType, delObj, "Invoke")); }
public void GeneratedStubFooCall() { FooRequest fooRequest = FooRequest.CreateBuilder().Build(); MockRepository mocks = new MockRepository(); IRpcChannel mockChannel = mocks.StrictMock <IRpcChannel>(); IRpcController mockController = mocks.StrictMock <IRpcController>(); TestService service = TestService.CreateStub(mockChannel); Action <FooResponse> doneHandler = mocks.StrictMock <Action <FooResponse> >(); using (mocks.Record()) { // Nasty way of mocking out "the channel calls the done handler". Expect.Call(() => mockChannel.CallMethod(null, null, null, null, null)) .IgnoreArguments() .Constraints(Is.Same(FooDescriptor), Is.Same(mockController), Is.Same(fooRequest), Is.Same(FooResponse.DefaultInstance), Is.Anything()) .Do((CallFooDelegate)((p1, p2, p3, response, done) => done(response))); doneHandler.Invoke(FooResponse.DefaultInstance); } service.Foo(mockController, fooRequest, doneHandler); mocks.VerifyAll(); }
public void AddKnownChannel(IRpcChannel channel) { if (channel == null || channel.ConnectionInfo == null) { throw new ArgumentNullException(nameof(channel)); } var connectionInfo = channel.ConnectionInfo; Uri?hostUrl = connectionInfo?.HostUrl; if (connectionInfo == null || (connectionInfo.ServerId == RpcServerId.Empty && hostUrl == null)) { throw new ArgumentException("Known connection must include a ServerId or HostUrl."); } lock (this.syncRoot) { if (this.idToKnownConnection.ContainsKey(channel.ConnectionInfo.ServerId) || (hostUrl != null && this.urlToKnownConnection.ContainsKey(hostUrl)) || this.idToServerConnection.ContainsKey(channel.ConnectionInfo.ServerId) || (hostUrl != null && this.urlToServerConnection.ContainsKey(hostUrl))) { throw new InvalidOperationException($"Known connection '{channel}' already added."); } if (connectionInfo.ServerId != RpcServerId.Empty) { this.idToKnownConnection.Add(connectionInfo.ServerId, channel); } if (connectionInfo.HostUrl != null) { this.urlToKnownConnection.Add(connectionInfo.HostUrl, channel); } } }
protected GrpcClientBase(IRpcChannel rpcChannel) { this._rpcChannel = rpcChannel ?? throw new ArgumentNullException(nameof(rpcChannel)); }
private object ImplementInterfaces(Type[] interfaceTypes, IRpcChannel channel, int remoteInstanceId, int localInstanceId) { if (!AllowNonPublicInterfaceAccess) { if (interfaceTypes.All(interfaceType => interfaceType.IsInterface && !interfaceType.IsPublic && !interfaceType.IsNestedPublic)) { throw new RpcFailedException("Cannot get non public interface."); } } RpcTypeDefinition type; lock (_proxyImplementations) { var hash = CreateTypesHash(interfaceTypes); if (!_proxyImplementations.TryGetValue(hash, out type)) { /* #if !NETSTANDARD && DEBUG * ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("RpcDynamicTypes"), * AssemblyBuilderAccess.RunAndSave); #endif*/ //add a destructor so we can inform other side about us not needing the object anymore var tb = _moduleBuilder.DefineType($"I{Guid.NewGuid():N}Shadow"); var invokerField = CreateConstructor(tb); var(localField, remoteField) = ImplementIRpcObjectProxy(tb); CreateDestructor(tb, invokerField, localField, remoteField); var allInterfaceTypes = AllowNonPublicInterfaceAccess ? interfaceTypes : interfaceTypes.Where(i => i.IsPublic || i.IsNestedPublic); foreach (var intf in allInterfaceTypes) { tb.AddInterfaceImplementation(intf); foreach (var method in intf.GetMethods().Where(m => !m.IsSpecialName)) { ImplementMethod(tb, method, invokerField, remoteField, true); } foreach (var property in intf.GetProperties()) { var prop = tb.DefineProperty(property.Name, property.Attributes, property.PropertyType, null); if (property.GetMethod != null) { prop.SetGetMethod(ImplementMethod(tb, property.GetMethod, invokerField, remoteField, true)); } if (property.SetMethod != null) { prop.SetSetMethod(ImplementMethod(tb, property.SetMethod, invokerField, remoteField, true)); } } foreach (var evnt in intf.GetEvents()) { if (evnt.AddMethod != null) { ImplementMethod(tb, evnt.AddMethod, invokerField, remoteField, true); } if (evnt.RemoveMethod != null) { ImplementMethod(tb, evnt.RemoveMethod, invokerField, remoteField, true, true); } } } type = new RpcTypeDefinition { Type = tb.CreateTypeInfo().AsType() }; type.LocalIdField = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance); type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance); _proxyImplementations.Add(hash, type); } } /* #if !NETSTANDARD && DEBUG * ab.Save(@"RpcDynamicTypes.dll"); #endif*/ var result = Activator.CreateInstance(type.Type, channel); Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null"); Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null"); type.LocalIdField.SetValue(result, localInstanceId); type.RemoteIdField.SetValue(result, remoteInstanceId); return(result); }
public abstract object GetProxyObject(IRpcChannel channel, Type[] interfaceTypes, int remoteInstanceId);