Hi Alex,
This is possible, from a code perspective, but you need to realize that
this is a change in the contracted interface, so there are no guarantees
that adding such a change at a later time will have zero impact on an
existing caller. For instance, if some caller implementation took a copy
of the WSDL at the time the contract between caller/callee was established,
and uses the schemas in that WSDL to validate proper XML schema compliance,
if you then later add properties to the class, and these get serialized,
the validation check on the caller's part will fail - resulting in issues
you may not anticipate.
However, if you are among those folks that like to think of XML as a better
comma delimited file, and you just seek out the elements you are looking
for (say with xpath) or with an optimized pull parser (like that found in
NET), then you can get away with this in most circumstances.
The way to add more properties depends on their type. For reference types
in .NET, just create a normal property or field, and place it at the end of
your class. You need to take some care that you only serialize either thru
fields or thru properties, and never mix them, since this can cause changes
added at end to appear in the middle. This is due to the way the
serializer first processes fields and then properties in order (or is it
the other way around)...
For reference types, they are not serialized if their values are null at
runtime. For value types, such as bool and int, you have to do something
slightly different. Value types never have a value, since as soon as you
declare a value type, it is assigned a value as it is initialized. For
this reason, value types would always be serialized. To get around this
and be able to support schema concepts such as minOccurs="0" in XML
elements and use="optional" in Xml attributes, the XML serializer provides
a means to flag when you want a value type to be serialized or not.
In general, I like serializing thru fields, and programming thru
properties. Here's an example:
public class foo
{
[EditorBrowsable(EditorBrowsableState.Advanced)]
public string fieldFoo1;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public string fieldFoo2;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public int fieldFoo3;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public boolean fieldFoo3Specified;
[XmlIgnore]
public string Foo1
{
get{ return fieldFoo1;}
set{ fieldFoo1 = value; }
}
[XmlIgnore]
public string Foo2
{
get{ return fieldFoo2; }
set { fieldFoo2 = value; }
}
[XmlIgnore]
public int Foo3
{
get { return fieldFoo3; }
set { fieldFoo3Specified = true; fieldFoo3 = value; }
}
public foo()
{
fieldFoo1 = String.Empty; // make the first field always have a
value
}
}
Now, when you serialize out of this class, you have always got a Foo1
element present. The remaining properties are optional. When you add to
this class, always add the public field at the end of the rest of the
public fields. This guarantees serialization order and your changes come
at the end. Then add a property to the class that is ignored by the XML
serializer.
The EditorBrowsable attribute on the fields means that for the most part,
intellisense helper tips won't expose the field members. This is good,
since you want the fields to be hidden from the programmer. They remain
public because the serializer today only serializes public data members on
classes that have public default constructors. The XmlIgnore attribute on
the properties makes sure that the serializer only outputs the field
content, and avoids the property setters completely.
An alternative way to do this is to only use fields, or only use public
properties and private fields. If you use properties, you must provide
both a read and write (get/set) behavior, elsewise the serializer will
ignore properties that do not have both getter and setter.
I hope this helps
Dan Rogers
Microsoft Corporation
--------------------
Thread-Topic: Optional properties
thread-index: AcTm2hWtV1KZThakSJOm/kEdin/vaA==
X-WBNR-Posting-Host: 198.133.214.10
From: =?Utf-8?B?QWxleCBEaW51?= <Alex (e-mail address removed)>
Subject: Optional properties
Date: Mon, 20 Dec 2004 13:23:01 -0800
Lines: 5
Message-ID: <
[email protected]>
MIME-Version: 1.0
Content-Type: text/plain;
charset="Utf-8"
Content-Transfer-Encoding: 7bit
X-Newsreader: Microsoft CDO for Windows 2000
Content-Class: urn:content-classes:message
Importance: normal
Priority: normal
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
Newsgroups: microsoft.public.dotnet.framework.aspnet.webservices
NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 10.40.1.29
Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA02.phx.gbl!cpmsftngxa06.phx.gbl!TK2MSFTNGP08
phx.gbl!TK2MSFTNGXA03.phx.gbl
Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27308
X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices
If you have a data class, Person, with two properties, FirstName and
LastName, and at a later stage you want to add a new optional property to the
class which is used in a web service. What is the best way to achieve this in
order to minimize the effect on the cosumers, who may be running .NET and
Java platforms.