- You should not use the DefaultValue attribute with an expandable property. No error message is generated if you do, but its Value is null (which causes problems -- most code assumed that if the property exists its Value also exists). It is also higher precedence than ShouldSerialize, so it blocks that from working.
- Unclear whether this is a bug or not. It was hard to find much about it on the net, but I did find some indicating it is a known issue, and I found an MSDN page that seemed to say you should use ShouldSerializePropertyName() for complex properties, and the DefaultValue attribute for simple ones. Hard to say whether that is the deliberate design, or whether that is bug-fix-by-documenting-it-as-a-feature.
- I'm still a bit wondering whether I am missing anything, because the built-in Point class does obey a DefaultValue attribute. I was unable to duplicate that behavior. I have no idea whether it is taking advantage of something not generally available, or whether I am just missing something.
- The DefaultValue attribute does work on the individual properties inside the expandable property. The problem with that is it is a hard-coded compile-time thing. It is hard to update it dynamically (Value is read-only, and SetValue() is not public). That means there is no way for the indicator that uses it to set that default value. The solution is to use ShouldSerialize here, too.
- Since there was not much on the net about this, I have no idea whether this is .NET 3.5 behavior that might get changed in a later .NET.
I have put together a simple demo indicator with an expandable property that works right, at least as far as I can tell. I managed to get all of the complexity, such as it is, into the class and accompanying code (a custom attribute and some type converters) so that it is simple for the indicator that uses it. My demo actually handles the default values better than Point does -- it shows the proper state of each of the member properties. Point does not -- everything changes between bold and dim simultaneously, so there is no way to tell which of its two member values in non-default. The demo source has quite a bit of commenting about how/why things are as they are.
If anyone is interested I can make the demo code available. Let me know and you can have a copy. All I ask is that you let me now if you find any errors, have any suggestions for improvement, etc.
Mr K: doing this work I ran into another case of the system pulling the rug out from underneath me with its frequent object re-creation. I had the constructor caching default value data for later use, and the object re-creation broke that. Fortunately, in this case I was able to identify the problem quickly and then work around it. I have no idea whether it is caused by NT, or whether it is inherent in .NET.
--EV
Comment