Skip to content

How to use Unity container extension to inject dependencies into WF Activity

dimaKudr edited this page Jun 19, 2012 · 1 revision

Unity.WF library defines WorkflowExtension class that is a Unity container extension and can be used to push dependencies from Unity container into workflow instance at the workflow initialisation stage.

Take a look at the following custom code activity:

public sealed class CalculatorActivity : CodeActivity
{
    [Dependency]
    public ICalcService Calculator { get; set; }

    public InArgument<int> A { get; set; }
    public InArgument<int> B { get; set; }
    public OutArgument<int> Result { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        var a = context.GetValue(A);
        var b = context.GetValue(B);
        var result = Calculator.Add(a, b);

        Result.Set(context, result);
    }
}

You can see that this activity has an external dependency:

[Dependency]
public ICalcService Calculator { get; set; }

This dependency is marked by [Dependency] attribute, so we would like it to be resolved by Unity container. Say we have properly configured Unity container instance.

var container = new UnityContainer();
container.RegisterType<ICalcService, CalcService>();

Let's begin from the simple case, when we want to execute just the instance of CalculatorActivity. In this situation Unity will resolve all dependencies automatically.

var activity = container.Resolve<FirstCalculatorActivity>();
var activityArgs = new Dictionary<string, object>
{
    { "A", 21 }, { "B", 21 }
};

var results = new WorkflowInvoker(activity).Invoke(activityArgs);

Assert.AreEqual(42, (int)results["Result"]);

OK. But what will happen in a bit more complex case? Let's imagine that we have XAML-based workflow that was created in Visual Studio designer, and somewhere in the middle it has CalculatorActivity. In such situation Unity does not have control over CalculatorActivity so it can't inject any dependencies. But don't worry. There is a way.

Firstly, we should add an instance of WorkflowExtension (from Unity.WF) to the container

container.AddNewExtension<WorkflowExtension>();

Secondly, we should instantiate our xaml-based workflow using Unity container.

var activity = container.Resolve<XamlBasedCompositeActivity>();

Finally, we can run our workflow using WorkflowInvoker (or WorkflowApplication) and will find that dependency was successfully injected.

var wfInvoker = new WorkflowInvoker(activity);
var results = wfInvoker.Invoke();
Assert.AreEqual(45, (int)results["CompositeResult"]);

That's it.