StateValue<T> issue

Topics: User Forum
Jan 11, 2007 at 9:23 AM
Has anyone else had a problem when using StateValue<int>, or presumably any other value type?

If i have the following declaration in my Controller class:

public StateValue<int> CustomerCount;

... how do I check whether it has been initialised? If I do the following;

if (CustomerCount.Value == 0)

... I get a NullReferenceException. Yet CustomerCount isn't null... and I can't check "CustomerCount.Value == null" because it is a value type, and therefore can't be null.

Have I missed something obvious, or is the guidance to always use reference types with StateValue? If so, should there be a constraint on the generic parameter?

Any help appreciated!
Jan 11, 2007 at 1:37 PM
I have tried this,

In ModuleQuickStart the StateValue<Customer> works fine.

But if you try to rewrite the ViewPresenterQuickStart to use the same code StateValue<Customer> is dosn't work.

The only difference in the code is that ModuleQuickStart uses ObjectBuilder to create the CustomerController.

So the solution lays in the ObjectBuilder, the buildup ensures that public fields are initialized.
Jan 11, 2007 at 1:48 PM
Lets review this again:

If you are using ObjectBuilder and the StateValue<int> is public, ObjectBuilder creates this field for you.

If you are hiding this field or not using ObjectBuilder, you have to create the StateValue by your selv.
Developer
Jan 11, 2007 at 1:51 PM
Hi, thanks for the feedback.
We have identified this bug and it will be fixed for the final release.

Mariano Szklanny
http://staff.southworks.net/mariano
Jan 11, 2007 at 2:15 PM
To clarify, I am indeed using ObjectBuilder (using a CreateNew attribute on the Controller as a parameter to the Presenter's constructor) and my StateValue<int> field is public.

I'm assuming Mariano has spotted something that can happen under these conditions that they are fixing for the big v1 drop - if so, thanks!

Simon
Developer
Jan 11, 2007 at 2:54 PM
Your assumption is correct - there was a bug when using the StateValue<T> class with value types, even though the class was created with ObjectBuilder. (BTW, the StateValue<T> class is not intended to be used with objects created manually with 'new').

Thanks,
Mariano Szklanny
http://staff.southworks.net/mariano
Jan 11, 2007 at 6:45 PM
I thought the StateValue<T> class was a good idea as a typed wrapper to the Session variable. Why would you recommend against using it without ObjectBuilder?
Developer
Jan 11, 2007 at 9:39 PM
I recommend against using it without ObjectBuilder because you will have to write extra code to:

- Instantiate the StateValue<T> field
- Get the Session bag in a way that your class still remains testable (for example, you could use the ISessionStateLocatorService service, which is used by the builder strategy that injects the StateValue<T> for you) and set it in the StateValue<T> field
- Set the KeyName for the field (this is the Session key used to identify the value in the Session bag)

Why would you do all that if ObjectBuilder already does it for you? :)

Mariano Szklanny
http://staff.southworks.net/mariano
Jan 11, 2007 at 10:26 PM
I indeed like the StateValue<T> class.

But im not found of the fact that u have to expose it public like u have done it in the ModuleQuickStart.

public class CustomersController
{
public StateValue<Customer> _currentCustomer;
public StateValue<List<Customer>> _customers;

My question is if there is another way to do it, without exposing the field as public? I tryed to use a setter property, but that dosn't work.
Jan 12, 2007 at 1:11 AM
Since I began to use CAB, I've been learning to live with it. It hurts, but it's the best way. :)
Jan 12, 2007 at 8:46 AM
Could you work around this by holding your state info in another class... e.g.;

public class StateFields
{
public StateValue<Customer> OrderingCustomer;
public StateValue<OrderList> Orders;
}

... and then take that as an argument to the constructor of your Controller...

public MyController(CreateNew StateFields stateInfo, ....)
{
// store privately
_stateInfo = stateInfo;
}

I admit I've not tried this, and it's first thing in the morning here so the brain cells haven't warmed up yet :-)

But I think this would meet your needs wouldn't it? It keeps the instance variable private to the Controller, yet still uses ObjectBuilder to create the State<T> fields.
Jan 12, 2007 at 9:22 AM
The solution

public class StateFields
{
public StateValue<Customer> OrderingCustomer;
public StateValue<OrderList> Orders;
}

worked.

The only difference i prefer is instead of class, im would call it a struct. And using a setter injektor.

CreateNew
public StateFields Fields
{
// private get { return _fields; }
set { _fields = value; }
}
Jan 12, 2007 at 9:25 AM
BTW: Thanks for the fix of The StateValue issue.
Jan 12, 2007 at 10:50 AM
I've been thinking about this for a while but I don't have a definite solution.

You could mark your setters with Obsolete(true). This way, no one can compile against it.

You could try to explicitly use ObjectBuilder to build these instances the same way the WebClientApplication does with the Page in the InnerPreRequestHandlerExecute method.
Jan 12, 2007 at 11:05 AM
I've tried my CreateNew/constructor solution above and it works fine... although I acknowledge the fields are still publicly accessible from the StateFields class, they are not exposed by the controller. I think that's the approach I'd be likely to use as it doesn't result in unnecessary properties to confuse the interface.

Alternatively you could define an IMyController interface that doesn't include your properties, and always store references to your controller using it... that way the properties are on the controller but not visible to developers. Don't like this solution though - feels like a hack!
Developer
Jan 12, 2007 at 4:12 PM
I invite you to check out the solution I posted here:
http://staff.southworks.net/blogs/mariano/archive/2007/01/12/How-to_3A00_-inject-StateValue_3C00_T_3E00_-objects-using-constructor-injection.aspx

Any feedback is welcome.
Thanks,
Mariano Szklanny
http://staff.southworks.net/mariano
Jan 12, 2007 at 8:53 PM
Thank U, Mariano

I love learning by Examples. Starting to understand the ObjectBuilder better day after day.

Benny
Jan 12, 2007 at 9:05 PM
Ditto - good article Mariano.