Injecting State from a parent WI to child WI

Topics: CAB & Smart Client Software Factory
Jan 31, 2006 at 3:51 PM
originally posted by: dirtysanchez33

I am having problems injecting the State from a parent WorkItem to a child WorkItem.

In the child workItem I declare a property like this:

State("Customer")
public Customer Customer
{
get { return (Customer)State"Customer"; }
set { State"Customer" = State; }
}

If I trace through this, I can see that the Object builder tries to inject the Customer object into the child WorkItem's state. However, at the time of injection, the child workitem's State object is null, so an attempt to assign to it throws an exception.

Even if I were to check for State == null, I still would not be able to propogate the State to the child workitem. The documentation says that the above should work, but clearly it doesn't.

Does anyone know any 'Good Practice' work arounds for this. I have heard elsewhere on these boards that creating a Service that the parent can use to manually set the State of the child (or the child can query this service to get the state it needs) is recommended as a work around, but this seems pretty clunky. The correct way seems to be through dependency injection, but obviously doesn't work in this case.

I also want to avoid the following:

From childWorkItem OnRunStarted():

State"Customer" = RootWorkItem.State"Customer";

because then the childWorkItem has to know that the state it's interested in resides in the RootWorkItem.

Any ideas?
Feb 1, 2006 at 5:02 AM
originally posted by: jolu1977

This may seem obvious but instead of injecting state into child workitems pass it in using a method.
Feb 1, 2006 at 6:13 AM
originally posted by: BradWilsonMSFT

There are really two concepts which shouldn't be mixed here (although I think we had done this earlier in some sample code). You should choose one of:

private Customer _customer;

State("Customer")
public Customer Customer
{
get { return _customer; }
set { _customer = value; }
}

or:

public Customer Customer
{
get { return (Customer)State"Customer"; }
set { State"Customer" = value; }
}

The former takes a moment-in-time snapshot of the customer value from state, and never updates the state based on new instances. The latter gives a real-time view of the customer value from state, and updates it based on new instances. Which one you will choose depends on what your needs are.

Hope that helps...
Feb 1, 2006 at 8:20 AM
originally posted by: dirtysanchez33

Thanks for the reply Brad. Your response sorta helps. The main issue is trying to inject state from the Parent WorkItem to the Child WorkItem automagically through dependency injection. While your first example acheives this, it doesn't actually inject the state into the Child's State object, it only injects it to a local variable. This leaves it up to the developer of the WorkItem to do the actual setting of the Child's State object. Not a big deal, but an extra step nonetheless.

The second example doesn't inject state from the Parent to the Child state, so doesn't really address the issue.

The work around I've come up with is to subclass WorkItem and perform the setting of the Child's state there:

public class StateInjectedWorkItem : WorkItem
{
private Dictionary<string, object> injectedState;

protected Dictionary<string, object> InjectedState
{
get { return injectedState; }
}

public StateInjectedWorkItem()
: base()
{
injectedState = new Dictionary<string, object>();
}

protected override void OnRunStarted()
{
base.OnRunStarted();

InjectState();
}


private void InjectState()
{
foreach (string key in injectedState.Keys)
{
Statekey = injectedStatekey;
}

injectedState.Clear();
injectedState = null;
}

}


So any workItem I have that I want to support state injection inherits from StateInjectedWorkItem. The state is injected into the InjectedState property instead of the State property (which is null at the time of injection). You then call the base.OnRunStarted() which will copy the InjectedState dictionary items over to the WorkItem.State property.

EG:

public class CustomerInformationWorkItem : Common.CAB.StateInjectedWorkItem
{

State("Customer")
public Customer Customer
{
set { InjectedState"Customer" = value; }
}


protected override void OnRunStarted()
{
base.OnRunStarted();

//State property now exists and is filled with the values set in InjectedState

}
}




Any thoughts on this?
Feb 9, 2006 at 6:19 PM
originally posted by: FrontierMal

I have encountered this same issue and have been tearing my hair out wondering why the State injection isn't happening as documented. Good to see I'm not the only one (ie. validates I'm not just misinterpreting the doco). dirtysanchez33, your solution is nice but I can't help but think life wasn't meant to be like this...

But at least I have an answer now, and a potential workaround. Good stuff mate, thanks.