/// <summary>
        /// Called when a method or property call is intercepted.
        /// </summary>
        /// <param name="invocation">Information about the call that was intercepted.</param>
        public void Intercept(IInvocation invocation)
        {
            m_Diagnostics.Log(
                LevelToLog.Trace,
                CommunicationConstants.DefaultLogTextPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    "Invoking {0}",
                    MethodToText(invocation.Method)));

            Task <ICommunicationMessage> result;

            try
            {
                var tuple = ToParameterData(invocation.Method, invocation.Arguments);
                result = m_TransmitCommandInvocation(
                    new CommandInvokedData(
                        CommandId.Create(invocation.Method),
                        tuple.Item3),
                    tuple.Item1,
                    tuple.Item2);
            }
            catch (EndpointNotContactableException e)
            {
                m_Diagnostics.Log(
                    LevelToLog.Error,
                    CommunicationConstants.DefaultLogTextPrefix,
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "Tried to invoke {0}, but failed to contact the remote endpoint.",
                        MethodToText(invocation.Method)));

                throw new CommandInvocationFailedException(Resources.Exceptions_Messages_CommandInvocationFailed, e);
            }
            catch (FailedToSendMessageException e)
            {
                m_Diagnostics.Log(
                    LevelToLog.Error,
                    CommunicationConstants.DefaultLogTextPrefix,
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "Tried to invoke {0}, but failed to send the message.",
                        MethodToText(invocation.Method)));

                throw new CommandInvocationFailedException(Resources.Exceptions_Messages_CommandInvocationFailed, e);
            }

            invocation.ReturnValue = ExtractMethodReturnFrom(invocation, result);
        }
        public void ToMessage()
        {
            var serializers = new Mock <IStoreObjectSerializers>();
            {
                serializers.Setup(s => s.HasSerializerFor(It.IsAny <Type>()))
                .Callback <Type>(t => Assert.IsTrue(typeof(int).Equals(t)))
                .Returns(true);
                serializers.Setup(s => s.SerializerFor(It.IsAny <Type>()))
                .Returns(new NonTransformingObjectSerializer());
            }

            var translator = new CommandInvocationConverter(serializers.Object);

            var id   = CommandId.Create(typeof(int).GetMethod("CompareTo", new[] { typeof(object) }));
            var data = new CommandInvocationData
            {
                Id             = new MessageId(),
                InResponseTo   = new MessageId(),
                Sender         = new EndpointId("a"),
                CommandId      = CommandIdExtensions.Serialize(id),
                ParameterTypes = new[]
                {
                    new SerializedType
                    {
                        FullName     = typeof(int).FullName,
                        AssemblyName = typeof(int).Assembly.GetName().Name
                    },
                },
                ParameterNames = new[]
                {
                    "other",
                },
                ParameterValues = new object[]
                {
                    1,
                }
            };
            var msg = translator.ToMessage(data);

            Assert.IsInstanceOf(typeof(CommandInvokedMessage), msg);
            Assert.AreSame(data.Id, msg.Id);
            Assert.AreSame(data.Sender, msg.Sender);
            Assert.AreEqual(id, ((CommandInvokedMessage)msg).Invocation.Command);
            Assert.AreEqual(data.ParameterTypes.Length, ((CommandInvokedMessage)msg).Invocation.Parameters.Length);
            Assert.AreEqual(typeof(int), ((CommandInvokedMessage)msg).Invocation.Parameters[0].Parameter.Type);
            Assert.AreEqual("other", ((CommandInvokedMessage)msg).Invocation.Parameters[0].Parameter.Name);
            Assert.AreEqual(1, ((CommandInvokedMessage)msg).Invocation.Parameters[0].Value);
        }
        public void FromMessage()
        {
            var serializers = new Mock <IStoreObjectSerializers>();
            {
                serializers.Setup(s => s.HasSerializerFor(It.IsAny <Type>()))
                .Returns(true);
                serializers.Setup(s => s.SerializerFor(It.IsAny <Type>()))
                .Returns(new NonTransformingObjectSerializer());
            }

            var translator = new CommandInvocationConverter(serializers.Object);

            var id  = CommandId.Create(typeof(int).GetMethod("CompareTo", new[] { typeof(object) }));
            var msg = new CommandInvokedMessage(
                new EndpointId("a"),
                new CommandInvokedData(
                    id,
                    new[]
            {
                new CommandParameterValueMap(
                    new CommandParameterDefinition(typeof(object), "other", CommandParameterOrigin.FromCommand),
                    1),
            }));
            var data = translator.FromMessage(msg);

            Assert.IsInstanceOf(typeof(CommandInvocationData), data);
            Assert.AreSame(msg.Id, data.Id);
            Assert.AreSame(msg.Sender, data.Sender);
            Assert.AreSame(msg.InResponseTo, data.InResponseTo);
            Assert.AreEqual(CommandIdExtensions.Serialize(id), ((CommandInvocationData)data).CommandId);
            Assert.AreEqual(msg.Invocation.Parameters.Length, ((CommandInvocationData)data).ParameterTypes.Length);
            Assert.AreEqual(
                msg.Invocation.Parameters[0].Parameter.Type.FullName,
                ((CommandInvocationData)data).ParameterTypes[0].FullName);
            Assert.AreEqual(
                msg.Invocation.Parameters[0].Parameter.Type.Assembly.GetName().Name,
                ((CommandInvocationData)data).ParameterTypes[0].AssemblyName);

            Assert.AreEqual(msg.Invocation.Parameters.Length, ((CommandInvocationData)data).ParameterNames.Length);
            Assert.AreEqual(
                msg.Invocation.Parameters[0].Parameter.Name,
                ((CommandInvocationData)data).ParameterNames[0]);

            Assert.AreEqual(msg.Invocation.Parameters.Length, ((CommandInvocationData)data).ParameterValues.Length);
            Assert.AreEqual(
                msg.Invocation.Parameters[0].Value,
                ((CommandInvocationData)data).ParameterValues[0]);
        }
        public void ProxyConnectingToMethodWithRetryCount()
        {
            var remoteEndpoint = new EndpointId("other");

            var local      = new EndpointId("local");
            var retryCount = -1;
            var timeout    = TimeSpan.MinValue;
            CommandInvokedMessage         intermediateMsg = null;
            SendMessageAndWaitForResponse sender          = (e, m, r, t) =>
            {
                retryCount = r;
                timeout    = t;

                intermediateMsg = m as CommandInvokedMessage;
                return(Task <ICommunicationMessage> .Factory.StartNew(
                           () => new SuccessMessage(remoteEndpoint, new MessageId()),
                           new CancellationToken(),
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            };

            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);

            var builder = new CommandProxyBuilder(local, sender, configuration.Object, systemDiagnostics);
            var proxy   = builder.ProxyConnectingTo <InteractionExtensionsTest.IMockCommandSetWithTaskReturn>(remoteEndpoint);

            var result = proxy.MyRetryMethod(10);

            result.Wait();

            Assert.IsTrue(result.IsCompleted);
            Assert.IsFalse(result.IsCanceled);
            Assert.IsFalse(result.IsFaulted);

            Assert.AreEqual(
                CommandId.Create(typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn).GetMethod("MyRetryMethod")),
                intermediateMsg.Invocation.Command);
            Assert.AreEqual(0, intermediateMsg.Invocation.Parameters.Length);
            Assert.AreEqual(10, retryCount);
            Assert.AreEqual(TimeSpan.FromMilliseconds(CommunicationConstants.DefaultWaitForResponseTimeoutInMilliSeconds), timeout);
        }
        public void Create()
        {
            var id             = new EndpointId("sendingEndpoint");
            var commandId      = CommandId.Create(typeof(int).GetMethod("CompareTo", new[] { typeof(object) }));
            var invocationData = new CommandInvokedData(
                commandId,
                new[]
            {
                new CommandParameterValueMap(
                    new CommandParameterDefinition(typeof(int), "other", CommandParameterOrigin.FromCommand),
                    1.0),
            });
            var msg = new CommandInvokedMessage(id, invocationData);

            Assert.AreSame(id, msg.Sender);
            Assert.AreSame(invocationData, msg.Invocation);
        }
        public void ProxyConnectingToMethodWithTypedTaskReturnWithFailedExecution()
        {
            var remoteEndpoint = new EndpointId("other");

            var local = new EndpointId("local");
            CommandInvokedMessage         intermediateMsg = null;
            SendMessageAndWaitForResponse sender          = (e, m, r, t) =>
            {
                intermediateMsg = m as CommandInvokedMessage;
                return(Task <ICommunicationMessage> .Factory.StartNew(
                           () => new FailureMessage(remoteEndpoint, new MessageId()),
                           new CancellationToken(),
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            };

            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);

            var builder = new CommandProxyBuilder(local, sender, configuration.Object, systemDiagnostics);
            var proxy   = builder.ProxyConnectingTo <InteractionExtensionsTest.IMockCommandSetWithTypedTaskReturn>(remoteEndpoint);

            var result = proxy.MyMethod(10);

            Assert.Throws <AggregateException>(result.Wait);

            Assert.IsTrue(result.IsCompleted);
            Assert.IsFalse(result.IsCanceled);
            Assert.IsTrue(result.IsFaulted);
            Assert.IsAssignableFrom(typeof(CommandInvocationFailedException), result.Exception.InnerExceptions[0]);

            Assert.AreEqual(
                CommandId.Create(typeof(InteractionExtensionsTest.IMockCommandSetWithTypedTaskReturn).GetMethod("MyMethod")),
                intermediateMsg.Invocation.Command);
            Assert.AreEqual(1, intermediateMsg.Invocation.Parameters.Length);
            Assert.AreEqual(typeof(int), intermediateMsg.Invocation.Parameters[0].Parameter.Type);
            Assert.AreEqual("input", intermediateMsg.Invocation.Parameters[0].Parameter.Name);
            Assert.AreEqual(10, intermediateMsg.Invocation.Parameters[0].Value);
        }
        public void InvokeWithTaskReturn()
        {
            var actionObject = new Mock <IMockCommandSet>();
            {
                actionObject.Setup(a => a.MethodWithoutReturnValue(It.IsAny <int>()))
                .Verifiable();
            }

            var commandIds = new List <CommandId>
            {
                CommandId.Create(typeof(IMockCommandSet).GetMethod("MethodWithoutReturnValue")),
            };
            var commandSets = new List <CommandDefinition>
            {
                new CommandDefinition(
                    commandIds[0],
                    new[]
                {
                    new CommandParameterDefinition(
                        typeof(int),
                        "someNumber",
                        CommandParameterOrigin.FromCommand),
                },
                    false,
                    (Action <int>)actionObject.Object.MethodWithoutReturnValue)
            };

            var endpoint = new EndpointId("id");

            ICommunicationMessage storedMsg  = null;
            SendMessage           sendAction =
                (e, m, r) =>
            {
                storedMsg = m;
            };
            var commands = new Mock <ICommandCollection>();
            {
                commands.Setup(c => c.CommandToInvoke(It.IsAny <CommandId>()))
                .Returns(commandSets[0]);
                commands.Setup(c => c.GetEnumerator())
                .Returns(commandIds.GetEnumerator());
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);

            var action = new CommandInvokedProcessAction(endpoint, sendAction, commands.Object, systemDiagnostics);

            action.Invoke(
                new CommandInvokedMessage(
                    new EndpointId("otherId"),
                    new CommandInvokedData(
                        commandIds[0],
                        new[]
            {
                new CommandParameterValueMap(
                    new CommandParameterDefinition(typeof(int), "someNumber", CommandParameterOrigin.FromCommand),
                    2),
            })));

            actionObject.Verify(a => a.MethodWithoutReturnValue(It.IsAny <int>()), Times.Once());
            Assert.IsInstanceOf <SuccessMessage>(storedMsg);
        }