예제 #1
0
            public static I CreateInstance(string instanceId, Connection connection, SendReceiveOptions options)
            {
                lock (cacheLocker)
                {
                    var key = new CachedRPCKey(instanceId, connection, typeof(I));
                    if (cachedInstances.ContainsKey(key))
                    {
                        return((I)cachedInstances[key]);
                    }

                    //Create the instance
                    var res = (I)Activator.CreateInstance(Type, instanceId, connection, options, typeof(I), Client.DefaultRPCTimeout);

                    Dictionary <string, FieldInfo> eventFields = new Dictionary <string, FieldInfo>();

                    foreach (var ev in typeof(I).GetEvents())
                    {
                        eventFields.Add(ev.Name, Type.GetField(ev.Name, BindingFlags.NonPublic | BindingFlags.Instance));
                    }

                    //Add the packet handler to deal with incoming event firing
                    connection.AppendIncomingPacketHandler <RemoteCallWrapper>(typeof(I).Name + "-RPC-LISTENER-" + instanceId, (header, internalConnection, eventCallWrapper) =>
                    {
                        try
                        {
                            //Let's do some basic checks on the data we've been sent
                            if (eventCallWrapper == null || !eventFields.ContainsKey(eventCallWrapper.name))
                            {
                                return;
                            }

                            var del = eventFields[eventCallWrapper.name].GetValue(res) as Delegate;

                            var sender = eventCallWrapper.args[0].UntypedValue;
                            var args   = eventCallWrapper.args[1].UntypedValue;

                            del.DynamicInvoke(sender, args);
                        }
                        catch (Exception) { }
                    });

                    connection.AppendIncomingPacketHandler <string>(typeof(I).Name + "-RPC-DISPOSE-" + instanceId, (header, internalConnection, eventCallWrapper) =>
                    {
                        (res as IRPCProxy).Dispose();
                    });

                    cachedInstances[key] = res;

                    return(res);
                }
            }
예제 #2
0
        /// <summary>
        /// Causes the provided <see cref="IRPCProxy"/> instance to be disposed
        /// </summary>
        /// <param name="clientObject">The <see cref="IRPCProxy"/> to dispose</param>
        public static void DestroyRPCClient(IRPCProxy clientObject)
        {
            if (!clientObject.IsDisposed)
            {
                clientObject.GetType().GetField("isDisposed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(clientObject, true);

                var connection = clientObject.ServerConnection;

                if (connection.ConnectionInfo.ConnectionState != ConnectionState.Shutdown)
                {
                    string packetTypeRequest = clientObject.ImplementedInterface.Name + "-REMOVE-REFERENCE-" + clientObject.ServerInstanceID;

                    RemoteCallWrapper wrapper = new RemoteCallWrapper();
                    wrapper.args       = new List <RPCArgumentBase>();
                    wrapper.name       = null;
                    wrapper.instanceId = clientObject.ServerInstanceID;

                    //Tell the server that we are no longer listenning
                    try { connection.SendObject <RemoteCallWrapper>(packetTypeRequest, wrapper); }
                    catch (Exception) { }

                    //Next remove the event packet handler
                    try { connection.RemoveIncomingPacketHandler(clientObject.ImplementedInterface.Name + "-RPC-LISTENER-" + clientObject.ServerInstanceID); }
                    catch (Exception) { }

                    //Next remove the server side dispose handler
                    try { connection.RemoveIncomingPacketHandler(clientObject.ImplementedInterface.Name + "-RPC-DISPOSE-" + clientObject.ServerInstanceID); }
                    catch (Exception) { }
                }

                //Finally remove the object from the cache. This guarentees that if we try to get the instance again at some time in the future
                //we won't end up with a disposed RPC object
                lock (cacheLocker)
                {
                    var cacheKey = new CachedRPCKey(clientObject.ServerInstanceID, clientObject.ServerConnection, clientObject.ImplementedInterface);

                    try { cachedInstances.Remove(cacheKey); }
                    catch (Exception) { }
                }
            }
        }