Context

The context is one of the three major components of Miruken. The other two major components being the protocol and the handler.

In this example we are simply creating a new context:

namespace Example.MirukenExamples.Context
{
    using Miruken.Context;

    public class CreatingAContext
    {
        public Context Context { get; set; }

        public CreatingAContext()
        {
            Context = new Context();
        }
    }
}

At the simplest level a context is a collection of handlers.

../../../../../_images/collectionOfHandlers.png

Here we are instantiating handlers and adding them to the context:

namespace Example.MirukenExamples.Context
{
    using Miruken.Context;

    public class AContextWithHandlerInstances
    {
        public Context Context { get; set; }

        public AContextWithHandlerInstances()
        {
            Context = new Context();
            Context.AddHandlers(new SomeHandler(), new AnotherHandler());
        }
    }
}

You can also rely on a container to create the handler instances. We like to use Castle Windsor, but as you can see by this example you can use any container you want. All you need is a handler in the context that implements IContainer and it will create the handler instances for you. My simple container here just instantiates instances and returns them.

namespace Example.MirukenExamples.Context
{
    using System;
    using Miruken.Callback;
    using Miruken.Concurrency;
    using Miruken.Container;
    using Miruken.Context;

    public class RelyingOnAContainerToResolveHandlers
    {
        public Context Context { get; set; }

        public RelyingOnAContainerToResolveHandlers()
        {
            Context = new Context();
            Context
                .AddHandlers(new ContainerHandler())
                .AddHandler<SomeHandler>()
                .AddHandler<AnotherHandler>();
        }
    }

    public class ContainerHandler: Handler, IContainer
    {
        public T Resolve<T>()
        {
            return (T) Resolve(typeof(T));
        }

        private object Resolve(Type type)
        {
            if (type == typeof(SomeHandler))
                return new SomeHandler();

            if (type == typeof(AnotherHandler))
                return new AnotherHandler();

            throw new ArgumentException("Unknown type");
        }

...

Hierarchical

Contexts are also hierarchical. They have a context graph witch mean they know their parent and can create children.

../../../../../_images/hierarchical.png

In this example we use the CreateChild() method to create a child context from an existing context:

namespace Example.MirukenExamples.Context
{
    using Miruken.Context;

    public class CreatingAChildContext
    {
        public IContext Parent { get; set; }
        public IContext Child  { get; set; }

        public CreatingAChildContext()
        {
            Parent = new Context();
            Child  = Parent.CreateChild();
        }
    }
}

Context Traversal

Context traversal is the concept of finding a handler for a message in the current context graph.

SelfOrAncestor is the default TraversingAxis which means that when Miruken is trying to handle a message it starts with the current context. If the current context cannot handle the message, the message will be passed to the parent to be handled. There are several other TraversingAxis. You can see them all described below.

../../../../../_images/selfOrAncestor.png ../../../../../_images/ancestor.png ../../../../../_images/child.png ../../../../../_images/descendant.png ../../../../../_images/descendantReversed.png ../../../../../_images/root.png ../../../../../_images/self.png ../../../../../_images/selfOrChild.png ../../../../../_images/selfOrDescendant.png ../../../../../_images/selfOrDescendantReversed.png ../../../../../_images/selfOrSibling.png ../../../../../_images/selfSiblingOrAncestor.png ../../../../../_images/sibling.png

Lifecycle

  • Context.End
  • Context.Ended