Dependency Injection of WorkItem State

Topics: CAB & Smart Client Software Factory
May 16, 2006 at 7:44 AM
originally posted by: yysun

What I wanted is to ask ObjectBuilder create an object into WorkItem's State

class MyWorkItem : WorkItem
{
Dependency(CreateType=typeof(MyClass), NotPresentBehavior=NotPresentBehavior.CreateNew)
public MyClass MyClass
{
get { return (MyClass) State"MyClass"; }
set { State"MyClass" = value; }
}

protected override void OnRunStarted()
{

base.OnRunStarted();
System.Diagnostics.Debug.Assert(MyClass != null, "MyClass has not been created");
}
}

The Assert failed.

Should I use the Dependency attribute or something else? Thanks in advance.
Jun 1, 2006 at 9:39 AM
originally posted by: rplaire

Have you tried the CreateNew attribute? Since you are just creating the instance in any case, this should serve you better.
Jun 1, 2006 at 11:59 AM
originally posted by: yysun

Thanks for your reply. I did try CreateNew. It dose not work either. To exclude the possibility of my class might have error, we can try create a Controller from CAB.

class MyWorkItem : WorkItem
{
CreateNew
public Controller Controller
{
get { return (Controller)State"Controller"; }
X set { State"Controller" = value; }
}

protected override void OnRunStarted()
{

base.OnRunStarted();
X System.Diagnostics.Debug.Assert(Controller != null, "Controller has not been created");
}
}

Noticed that, if put break points at the X sign above and add State to watch, you will see the State.ID actually are different at those two breakpoints. Are there two State objects created?
Jun 2, 2006 at 12:59 PM
originally posted by: rplaire

Are you accessing the correct WorkItem state? WorkItems don't share State...
Jun 2, 2006 at 2:31 PM
originally posted by: yysun

My code is only the 15 lines listed above.

What I tried to achieve is asking ObjectBuilder create an object into the State, so that I can use it in the OnRunStarted() function.

The result is that the object was created and was put in State property, but in the OnRunStarted function, either the State lost or State content lost, so I got only null.
Jun 2, 2006 at 3:29 PM
originally posted by: rplaire

Is it your Root WorkItem? How does it get created?
Jun 3, 2006 at 2:49 AM
originally posted by: yysun

It is the root workitem and created in the mian program.

class Program : FormShellApplication<MyWorkItem, MainForm>
{
STAThread
static void Main()
{
new Program().Run();
}
}

Here is the source code,
http://www.wbeditor.com/downloads/MyTest.zip
Jun 3, 2006 at 6:43 AM
originally posted by: rplaire

It's an interesting problem.

You are right, the Controller seems to disappear. You can see it being created, and then in the OnRunStarted method, the Assert fails. Here's why:

There are two methods in the WorkItem: InitializeRootWorkItem and InitializeWorkItem. The first one is called by virtue of your WorkItem being included in the FormShellApplication subclassing. The second is run because it has the InjectionMethod attribute on it, and when your WorkItem is initialized by ObjectBuilder, it is called. This in turn calls the InitializeState method, which was called in the earlier invocation of InitializeRootWorkItem. When it was called in InitializeRootWorkItem, your Controller was created. When it is called the second time, in InitializeWorkItem, it dumps the state through a call to ReleaseState() - your created controller is lost.

It seems like one of those unexpected "features" of the framework. My suggestion is that Controllers don't belong in the State anyway - they belong in Services.

CreateNew
public Controller Controller
{
get { return base.Services.Get<Controller>(); }
set { base.Services.Add<Controller>(value); }
}

-rory
Jun 3, 2006 at 9:44 AM
originally posted by: yysun

Thanks again for the suggestion.

I used Controller just as an example class. What I actural needed is that an object in the State (as in my original post it is MyClass).

The idea of using State is to let views created from this work item can use the State attribute to access the object, like

SmartPart
public partial class MyView : UserControl
{
private Controller controller;

State
public Controller Controller
{
set { controller = value; }
}
}


At beginning I thought of using service, but it comes with another problem.
For 2 smart part views, they cannot get service by interfaces.


SmartPart
public partial class CustomerListView : UserControl
{
private ICustomerListService service = null;

ServiceDependency
public ICustomerListService Service
{
set { service = value; }
}
}

SmartPart
public partial class CustomerDetailView : UserControl
{
private ICustomerDetailService service = null;

ServiceDependency
public ICustomerDetailService Service
{
set { service = value; }
}
}


Service(typeof(ICustomerDetailService))
Service(typeof(ICustomerListService))
public class CustomerService: ICustomerDetailService, ICustomerListService
{
}

Service attribute dose not allow multiple instance, so it's another dead end.