コード例 #1
0
        public void A_loopback_registry()
        {
            Address   = new Uri("loopback://localhost/");
            ReceivedA = new Future <A>();

            Registry = ActorRegistryFactory.New(x =>
            {
                x.Remote(r =>
                {
                    r.ListenTo(Address);
                });
            });

            ActorId = Guid.NewGuid();
            Actor   = AnonymousActor.New(inbox =>
            {
                inbox.Loop(loop =>
                {
                    loop.Receive <Message <A> >(message =>
                    {
                        ReceivedA.Complete(message.Body);

                        loop.Continue();
                    });
                });
            });

            Registry.Register(ActorId, Actor);
        }
コード例 #2
0
ファイル: ActorAccountSpecs.cs プロジェクト: mambrus/cslabs
        public void Newly_created_account_should_have_correct_balence_and_credit()
        {
            ActorRef      account = ActorFactory.Create(inbox => new AccountActor(inbox, 100.0m)).GetActor();
            Future <bool> result  = new Future <bool>();

            decimal balance         = 0xDEADBEEF;
            decimal availableCredit = 0xDEADBEEF;
            decimal creditLimit     = 0xDEADBEEF;

            AnonymousActor.New(inbox =>
            {
                account.Request(new QueryAccountBalance(), inbox)
                .Receive <AccountBalance>(message =>
                {
                    balance         = message.Balance;
                    availableCredit = message.AvailableCredit;
                    creditLimit     = message.CreditLimit;

                    Console.WriteLine("Balance={0}, Credit={1}, Limit={2}",
                                      balance, availableCredit, creditLimit);
                    result.Complete(true);
                });
            });

            result.WaitUntilCompleted(5.Seconds());
            Assert.True(balance == 0 && availableCredit == 100.0m && creditLimit == 100.0m);
        }
コード例 #3
0
        public void Should_properly_handle_the_response()
        {
            var     response = new FutureChannel <Purchased>();
            decimal price    = 0.0m;

            AnonymousActor.New(inbox =>
            {
                Auction.Request(new Ask(Id), inbox)
                .Within(30.Seconds())
                .Receive <Response <Status> >(m => status =>
                {
                    price = status.Body.CurrentBid;
                    Auction.Request(new Buy(status.Body.Token, 1), inbox)
                    .Within(30.Seconds())
                    .Receive <Response <Purchased> >(pm => pmsg => response.Complete(pmsg.Body))
                    .Otherwise(() => {});
                })
                .Receive <Response <Ended> >(m => ended => {});
            });

            response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response");

            response.Value.AuctionId.ShouldEqual(Id);
            response.Value.Quantity.ShouldEqual(1);
            response.Value.Price.ShouldEqual(price);
        }
コード例 #4
0
        public void When_actor_handles_messages_Then_it_calls_the_correct_handler()
        {
            var          receivedStrings     = new List <string>();
            var          receivedInts        = new List <int>();
            var          receivedFloats      = new List <float>();
            var          receivedObjects     = new List <object>();
            var          allRecievedMessages = new List <object>();
            Func <Actor> actorFactory        = () => AnonymousActor.Create(c =>
            {
                // ReSharper disable ConvertClosureToMethodGroup
                c.AddReceiver(typeof(object), msg => { allRecievedMessages.Add(msg); return(false); });
                c.Receive <float>(f => receivedFloats.Add(f));
                c.Receive <int>(i => receivedInts.Add(i));
                c.ReceiveAny(o => receivedObjects.Add(o));
                c.Receive <string>(s => receivedStrings.Add(s));               //Since we have a Catch-all above then no floats should end up here
                // ReSharper restore ConvertClosureToMethodGroup
            });
            var actor = ActorHelper.CreateInitializedActorDirectly(actorFactory);

            actor.HandleMessage(1.0f);
            actor.HandleMessage(2);
            actor.HandleMessage(true);
            actor.HandleMessage("4");

            receivedFloats.Should().BeEquivalentTo(1.0f);
            receivedInts.Should().BeEquivalentTo(2);
            receivedObjects.Should().BeEquivalentTo(true, "4");
            receivedStrings.Should().BeEmpty();
            allRecievedMessages.Should().BeEquivalentTo(1.0f, 2, true, "4");
        }
コード例 #5
0
        public void Should_properly_serialize_a_response()
        {
            var actor = AnonymousActor.New(inbox =>
            {
                _channel.Respond(new Test
                {
                    Name = "Magic"
                }, "21");
            });

            ThreadUtil.Sleep(1.Seconds());
        }
コード例 #6
0
        public void An_exit_is_sent_to_an_actor()
        {
            _receivedA = new Future <A>();

            _actor = AnonymousActor.New(inbox =>
            {
                inbox.Receive <A>(message =>
                {
                    _receivedA.Complete(message);
                });
            });
        }
コード例 #7
0
        public void Should_prevent_the_actor_from_exiting()
        {
            AnonymousActor.New(inbox =>
            {
                _actor.Request <Exit>(inbox)
                .Within(5.Seconds())
                .Receive <Response <Exit> >(x => { });
            });
            _intercepted.WaitUntilCompleted(5.Seconds()).ShouldBeTrue("Exit was not intercepted");

            _actor.Send(new A());
            _receivedA.WaitUntilCompleted(5.Seconds()).ShouldBeTrue("A was not handled, did actor exit?");
        }
コード例 #8
0
ファイル: Repeat_Specs.cs プロジェクト: yonglehou/Stact
        public void Should_support_the_repeat_syntax()
        {
            var completed = new Future <Status>();

            ActorRef auction = AnonymousActor.New(inbox =>
            {
                decimal currentBid = 0.0m;

                inbox.Loop(loop =>
                {
                    loop.Receive <Request <Bid> >(request =>
                    {
                        if (request.Body.MaximumBid > currentBid)
                        {
                            currentBid = request.Body.MaximumBid;
                        }

                        request.Respond(new StatusImpl
                        {
                            CurrentBid = currentBid
                        });

                        loop.Continue();
                    })
                    .Receive <Request <Ask> >(request =>
                    {
                        request.Respond(new StatusImpl
                        {
                            CurrentBid = currentBid
                        });

                        loop.Continue();
                    });
                });
            });

            ActorRef bidder = AnonymousActor.New(inbox =>
            {
                auction.Request(new BidImpl(13.5m), inbox)
                .Receive <Response <Status> >(bidResponse =>
                {
                    auction.Request <Ask>(inbox)
                    .Receive <Response <Status> >(askResponse => completed.Complete(askResponse.Body));
                });
            });

            completed.WaitUntilCompleted(5.Seconds()).ShouldBeTrue();

            bidder.Exit();
            auction.Exit();
        }
コード例 #9
0
        public void Should_not_receive_a_response_to_a_stupid_message()
        {
            var response = new FutureChannel <bool>();

            AnonymousActor.New(inbox =>
            {
                Auction.Request(new Ask(new Guid()), inbox)
                .Within(1.Seconds())
                .Receive <Response <Status> >(m => status => {})
                .Otherwise(() => response.Complete(true));
            });

            response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for otherwise to be called");
        }
コード例 #10
0
        public void A_stream_of_messages_is_received()
        {
            ActorFactory <Agent> agentFactory = ActorFactory.Create(inbox => new Agent(inbox));

            ActorRef agent = agentFactory.GetActor();

            for (int i = 0; i < _count; i++)
            {
                agent.Send(new Add
                {
                    Value = i
                });

                if (i == 100)
                {
                    agent.Send <Suspend>();
                }

                if (i == 500)
                {
                    agent.Send <Resume>();
                }
            }

            _response = new Future <Status>();
            var actor = AnonymousActor.New(inbox =>
            {
                Action loop = null;
                loop        = () =>
                {
                    agent.Request(new Status(), inbox)
                    .Receive <Response <Status> >(response =>
                    {
                        if (response.Body.Count == _count)
                        {
                            _response.Complete(response.Body);
                        }
                        else
                        {
                            loop();
                        }
                    });
                };

                loop();
            });

            _response.WaitUntilCompleted(8.Seconds());
        }
コード例 #11
0
        public void Should_receive_the_expected_value()
        {
            var response = new FutureChannel <Status>();

            AnonymousActor.New(inbox =>
            {
                Auction.Request(new Ask(Id), inbox)
                .Within(30.Seconds())
                .Receive <Response <Status> >(m => status => response.Complete(status.Body))
                .Receive <Response <Ended> >(m => ended => {});
            });

            response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response");

            response.Value.AuctionId.ShouldEqual(Id);
        }
コード例 #12
0
        public void Easy_syntax_love()
        {
            ActorFactory <QuoteService> factory =
                StateMachineActorFactory.Create <QuoteServiceWorkflow, QuoteService>(inbox => new QuoteService(inbox), x =>
            {
                x.AccessCurrentState(s => s.CurrentState);

                x.Initially()
                .When(e => e.GetQuoteRequest)
                .Then(i => i.SendQuoteRequest)
                .TransitionTo(s => s.WaitingForResponse);

                x.During(s => s.WaitingForResponse)
                .When(e => e.CancelRequest)
                .Then(i => i.Cancel)
                .Finalize();
            });

            ActorRef service = factory.GetActor();


            var response = new Future <Response <RequestSent> >();

            var actor = AnonymousActor.New(inbox =>
            {
                service.Request(new GetQuote
                {
                    Symbol = "MSFT"
                }, inbox)
                .Receive <Response <RequestSent> >(r =>
                {
                    service.Request(new GetQuote
                    {
                        Symbol = "AAPL"
                    }, inbox)
                    .Receive <Response <RequestSent> >(rr =>
                    {
                        response.Complete(r);
                    });
                });
            });

            response.WaitUntilCompleted(5.Seconds()).ShouldBeTrue();

            service.Exit();
        }
コード例 #13
0
            public ParentWithFailingChildActor(Mailbox failingChildMailbox, IEnumerable <Mailbox> siblingMailboxes, SupervisorStrategy supervisorStrategy = null)
            {
                _supervisorStrategy = supervisorStrategy;
                var failingChildProps = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { throw new Exception(); }))
                {
                    MailboxCreator = () => failingChildMailbox
                };
                Func <Mailbox, ActorCreationProperties> createSibling = m => new DelegateActorCreationProperties(() => new NoopActor())
                {
                    MailboxCreator = () => m
                };

                var failingChild = CreateActor(failingChildProps, "FailingChild");

                siblingMailboxes.ForEach((m, i) => CreateActor(createSibling(m), "Sibling" + i));
                ReceiveAnyAndForward(failingChild);
            }
コード例 #14
0
        public void Should_receive_the_alternate_ending_if_it_is_such()
        {
            Auction.Send(new End());

            var response = new FutureChannel <Ended>();

            AnonymousActor.New(inbox =>
            {
                Auction.Request(new Ask(Id), inbox)
                .Within(30.Seconds())
                .Receive <Response <Status> >(m => status => {})
                .Receive <Response <Ended> >(m => ended => response.Complete(ended.Body));
            });

            response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response");

            response.Value.AuctionId.ShouldEqual(Id);
        }
コード例 #15
0
ファイル: Fault_Specs.cs プロジェクト: yonglehou/Stact
        public void Should_receive_a_fault_message()
        {
            var received = new Future <Fault>();

            AnonymousActor.New(inbox =>
            {
                inbox.Receive <Fault>(fault =>
                {
                    received.Complete(fault);
                });

                throw new NotImplementedException("A");
            });

            received.WaitUntilCompleted(5.Seconds()).ShouldBeTrue();
            received.Value.Message.ShouldEqual("A");

            Trace.WriteLine(received.Value.StackTrace);
        }
コード例 #16
0
        public void An_exit_is_sent_to_an_actor_that_intercepts_exit()
        {
            _intercepted = new Future <Exit>();
            _receivedA   = new Future <A>();

            _actor = AnonymousActor.New(inbox =>
            {
                inbox.Receive <Request <Exit> >(request =>
                {
                    _intercepted.Complete(request.Body);
                    request.Respond(request.Body);
                });

                inbox.Receive <A>(message =>
                {
                    _receivedA.Complete(message);
                });
            });
        }
コード例 #17
0
        public void When_an_actor_crashes_during_handling_message_Then_the_actors_mailbox_gets_suspended()
        {
            var system = new TestActorSystem();

            system.Start();

            var mailbox = new TestMailbox(system.CreateDefaultMailbox());
            var props   = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { throw new Exception(); }))
            {
                MailboxCreator = () => mailbox
            };

            var actor = system.CreateActor(props);

            actor.Send("A trigger message that will cause actor to fail", null);
            var suspendCalls = mailbox.GetStateChangesFor(TestMailbox.StateChange.Suspend);

            suspendCalls.Count.Should().Be(1);
        }
コード例 #18
0
            public void Send(ConnectionContext context)
            {
                AnonymousActor.New(inbox =>
                {
                    _serviceCoordinator.Send <Request <ServiceStatus> >(new RequestImpl <ServiceStatus>(inbox, new ServiceStatus()));

                    inbox.Receive <Response <ServiceStatus> >(response =>
                    {
                        var view = new DashboardView(response.Body.Services);

                        context.Response.RenderSparkView(view, "dashboard.html");
                        context.Complete();
                    }, 30.Seconds(), () =>
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.RequestTimeout;
                        context.Complete();
                    });
                });
            }
コード例 #19
0
        public void When_two_actors_are_linked()
        {
            _a = AnonymousActor.New(inbox =>
            {
                inbox.Receive <Die>(x =>
                {
                    inbox.Exit();
                });
            });

            _b = AnonymousActor.New(inbox =>
            {
                _a.Link(inbox);

                inbox.Receive <Die>(x =>
                {
                });
            });
        }
コード例 #20
0
        public void Something()
        {
            ActorRef actor = AnonymousActor.New(inbox =>
            {
                inbox.Loop(loop =>
                {
                    loop.Receive <Request <Add> >(message =>
                    {
                        int result = message.Body.Left + message.Body.Right;

                        Trace.WriteLine("Responding with " + result + " on thread "
                                        + Thread.CurrentThread.ManagedThreadId);

                        message.Respond(new AddResult
                        {
                            Result = result
                        });

                        loop.Continue();
                    });


                    loop.Receive <Exit>(msg =>
                    {
                        inbox.Exit();
                        loop.Continue();
                    });
                });
            });

            var future = new Future <AddResult>();

            AnonymousActor.New(inbox =>
                               actor.Request(new Add
            {
                Left  = 56,
                Right = 23
            }, inbox)
                               .Receive <AddResult>(response => future.Complete(response)));

            future.WaitUntilCompleted(8.Seconds()).ShouldBeTrue("Didn't responsd");
        }
コード例 #21
0
        public void When_watching_another_actor_Then_a_Watch_message_is_sent_to_that_actor()
        {
            var system = new TestActorSystem();

            system.Start();

            var mailbox           = new TestMailbox(system.CreateDefaultMailbox());
            var watchedActorProps = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { }))
            {
                MailboxCreator = () => mailbox
            };
            var watchedActor = system.CreateActor(watchedActorProps, "WatchedActor");
            var watcher      = system.CreateActor(ActorCreationProperties.Create(() => new WatchingActor(watchedActor)), "Watcher");

            watcher.Send("watch", null);
            var watchMessages = mailbox.GetEnquedSystemMessagesOfType <WatchActor>();

            watchMessages.Should().HaveCount(1);
            watchMessages[0].Watcher.Should().BeSameAs(watcher);
        }
コード例 #22
0
        public void Should_not_call_the_other_receive_handlers()
        {
            var statusResponse = new FutureChannel <Status>();
            var endedResponse  = new FutureChannel <Ended>();

            AnonymousActor.New(inbox =>
            {
                Auction.Request(new Ask(Id), inbox)
                .Within(10.Seconds())
                .Receive <Response <Status> >(m => status =>
                {
                    statusResponse.Complete(status.Body);
                    Auction.Send(new End());
                    Auction.Request(new Ask(Id), inbox);
                })
                .Receive <Response <Ended> >(m => ended => endedResponse.Complete(ended.Body));
            });

            statusResponse.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response");
            endedResponse.WaitUntilCompleted(2.Seconds()).ShouldBeFalse("The receiver for Ended should not have been called.");
        }
コード例 #23
0
ファイル: RemoteActorTest.cs プロジェクト: yonglehou/Stact
        public void Run()
        {
            Trace.Listeners.Add(new ConsoleTraceListener());

            const string remoteAddress = "rm://234.0.0.7:40001/";

            Guid id = CombGuid.Generate();

            ActorRegistry registry = ActorRegistryFactory.New(x =>
            {
                x.Remote(r => r.ListenTo(remoteAddress));
            });

            ActorRef server = AnonymousActor.New(inbox =>
            {
                inbox.Receive <Response <Hello> >(message =>
                {
                    Console.WriteLine("Hi!");
                    Console.WriteLine("Request ID: " + message.RequestId);
                });
            });


            registry.Register(id, server);

            var actorAddress = new ActorUrn(remoteAddress, id);

            registry.Select(actorAddress, actor =>
            {
                actor.Send <Response <Hello> >(new ResponseImpl <Hello>(new Hello
                {
                    MyNameIs = "Joe",
                }, "27"));
            }, () => {});

            ThreadUtil.Sleep(5.Seconds());

            registry.Shutdown();
        }
コード例 #24
0
ファイル: SupervisorActor.cs プロジェクト: yonglehou/Stact
        public void HandleStop(Request <Stop> request)
        {
            IEnumerator <ActorRef> next = _inbox.LinkedActors.GetEnumerator();

            if (next.MoveNext())
            {
                AnonymousActor.New(x => x.Loop(loop =>
                {
                    next.Current.Request <Stop>(x)
                    .Receive <Response <Stop> >(response =>
                    {
                        if (next.MoveNext())
                        {
                            loop.Continue();
                        }
                        else
                        {
                            request.Respond();
                        }
                    });
                }));
            }
        }
コード例 #25
0
        public void Adding_an_actor_to_a_registry()
        {
            _auctionFactory = ActorFactory.Create(inbox => new Auction(inbox));

            _auctionId = CombGuid.Generate();

            ActorRef auction = _auctionFactory.GetActor();

            ActorRegistry registry = ActorRegistryFactory.New(x =>
            {
                //x.Remote(r => r.ListenTo("rm://234.0.0.7:40001"));
            });

            registry.Register(_auctionId, auction);

            _response = new Future <Response <Bid> >();

            AnonymousActor.New(inbox =>
            {
                registry.Request <Bid>(new BidImpl(27.42m),
                                       header => { header.DestinationAddress = new ActorUrn(_auctionId); }, inbox)
                .Receive <Response <Bid> >(x => _response.Complete);
            });

            _response.WaitUntilCompleted(5.Seconds()).ShouldBeTrue();

            // need to proxy the channel with headers somehow...

            // untyped channel => channel mapper -> actor instance

            // DestinationAddress -> set by outbound channel proxy on message<>
            // SourceAddress -> set by outbound channel proxy when available (not likely)
            // ResponseAddress -> set by outbound channel for ResponseChannel on Request to map to channel
            // Id -> system assigned id
            // DestinationAddress = urn:actor:554FC958-4661-4FE9-94F5-21D190417BCC
        }
コード例 #26
0
        public void Should_not_require_extensive_namespace_references()
        {
            var responded = new Future <MyResponse>();

            ActorRef server = AnonymousActor.New(inbox =>
            {
                inbox.Receive <Request <MyRequest> >(request =>
                {
                    // send our response
                    request.Respond(new MyResponse());
                });
            });

            ActorRef client = AnonymousActor.New(inbox =>
            {
                server.Request(new MyRequest(), inbox)
                .Receive <Response <MyResponse> >(response => responded.Complete(response.Body));
            });

            responded.WaitUntilCompleted(2.Seconds()).ShouldBeTrue();

            server.Exit();
            client.Exit();
        }
コード例 #27
0
ファイル: ActorAccountSpecs.cs プロジェクト: mambrus/cslabs
        public void Charging_an_account_async_should_still_adjust_the_balence()
        {
            ActorRef account = ActorFactory.Create(inbox => new AccountActor(inbox, 100.0m)).GetActor();

            decimal balance         = 0xDEADBEEF;
            decimal availableCredit = 0xDEADBEEF;
            decimal creditLimit     = 0xDEADBEEF;

            #region  Charge 3 times with 10.0 async

            AnonymousActor.New(inbox =>
            {
                account.Send(new ChargeAccount()
                {
                    Amount = 10
                });
            });

            AnonymousActor.New(inbox =>
            {
                account.Send(new ChargeAccount()
                {
                    Amount = 10
                });
            });

            AnonymousActor.New(inbox =>
            {
                account.Send(new ChargeAccount()
                {
                    Amount = 10
                });
            });

            #endregion

            #region Loop until available credit is correct but fail if more than 50 times

            for (int i = 0; availableCredit != 70.0m && i < 100; i++)
            {
                Future <bool> result = new Future <bool>();

                //Fire of listeners serially and with some time apart
                AnonymousActor.New(inbox =>
                {
                    account.Request(new QueryAccountBalance(), inbox)
                    .Receive <AccountBalance>(message =>
                    {
                        balance         = message.Balance;
                        availableCredit = message.AvailableCredit;
                        creditLimit     = message.CreditLimit;

                        Console.WriteLine("Balance={0}, Credit={1}, Limit={2}",
                                          balance,
                                          availableCredit,
                                          creditLimit);

                        Thread.Sleep(1000);
                        result.Complete(true);
                    });
                });
                result.WaitUntilCompleted(5.Seconds());
                Console.WriteLine("Listener {0} completed", i);
                Thread.Sleep(1000);

                Assert.True(i < 50);
            }

            #endregion

            Assert.True(balance == 30 && availableCredit == 70.0m && creditLimit == 100.0m);
        }
コード例 #28
0
        public void When_an_actor_crashes_during_handling_message_Then_it_gets_recreated()
        {
            var system = new TestActorSystem();

            system.Start();

            var numberOfCreateCalls = 0;
            var props = new DelegateActorCreationProperties(() => { numberOfCreateCalls++; return(AnonymousActor.Create <object>(_ => { throw new Exception(); })); });

            var actor = system.CreateActor(props);

            numberOfCreateCalls.Should().Be(1);
            actor.Send("A trigger message that will cause actor to fail", null);
            numberOfCreateCalls.Should().Be(2);
        }
コード例 #29
0
        public void When_actor_forwards_messages_of_specific_types_Then_it_calls_send_on_receiving_actor()
        {
            var testActorSystem = new TestActorSystem();

            testActorSystem.Start();
            TestActor recipientActor  = null;
            var       recipient       = testActorSystem.CreateActor(ActorCreationProperties.Create(() => { recipientActor = new TestActor(); return(recipientActor); }));
            var       receivedObjects = new List <object>();
            var       sut             = testActorSystem.CreateActor(ActorCreationProperties.Create(() => AnonymousActor.Create(c =>
            {
                // ReSharper disable ConvertClosureToMethodGroup
                c.ReceiveAndForward <int>(recipient);
                c.ReceiveAndForward <float>(recipient);
                c.ReceiveAny(o => receivedObjects.Add(o));
                // ReSharper restore ConvertClosureToMethodGroup
            })));

            var senderActor = testActorSystem.CreateActor(ActorCreationProperties.Create(() => new SendingActor(sut, 1, "2", 3.0f)));

            senderActor.Send("Send 1 2 and 3.0", null);
            recipientActor.ReceivedMessages.Should().HaveCount(2);
            recipientActor.ReceivedMessages[0].Item1.Should().BeSameAs(senderActor);
            recipientActor.ReceivedMessages[0].Item2.Should().Be(1);
            recipientActor.ReceivedMessages[1].Item1.Should().BeSameAs(senderActor);
            recipientActor.ReceivedMessages[1].Item2.Should().Be(3.0f);
            receivedObjects.Should().BeEquivalentTo(new object[] { "2" });
        }
コード例 #30
0
            public TestActor(ActorSystem system, bool childMailboxShouldBeOpen = true)
            {
                Replies = new List <string>();
                var childMailbox = new DelayedTestMailbox(system.CreateDefaultMailbox());
                var child        = CreateActor(new DelegateActorCreationProperties(() => AnonymousActor.Create(c => c.ReceiveAny((msg, sender) => sender.Reply(msg))))
                {
                    MailboxCreator = () => childMailbox
                }, "Child");

                if (childMailboxShouldBeOpen)
                {
                    childMailbox.Open();
                }

                Watch(child);

                Receive <WatchedActorTerminated>(terminated => ReceivedTerminate = true, m => m.TerminatedActor == child); //Record that child terminated
                Receive <string>(_ => child.Send(StopActor.Instance, Self), s => s == "stopChild");                        //Send Stop to child when any other message is received
                Receive <string>(_ => childMailbox.Open(), s => s == "openChildMailbox");
                Receive <string>(s => Replies.Add(s), _ => Sender.Path == child.Path);                                     //Record replies from child
                ReceiveAny(m => child.Send(m, Self));                                                                      //Forward all other messages
            }