Serialization of indexers

  • Thread starter Thread starter Pete Davis
  • Start date Start date
P

Pete Davis

I'm writing an XML serializer (similar to the MS XMLSerializer). It uses
reflection to get the values from a class/struct. The one area I'm confused
on is indexers. I can get the indexer PropertyInfo and the ParameterInfo
stuff, but I can't possibly know the range of valid values nor what the
underlying storage is.

How is this normally handled?

Should I just ignore the indexer and simply serialize the fields?

Pete
 
Pete said:
I'm writing an XML serializer (similar to the MS XMLSerializer). It
uses reflection to get the values from a class/struct. The one area
I'm confused on is indexers. I can get the indexer PropertyInfo and
the ParameterInfo stuff, but I can't possibly know the range of valid
values nor what the underlying storage is.

How is this normally handled?

Should I just ignore the indexer and simply serialize the fields?

Yes, ignore it. Take a cue from .NET serialization. It will only
serialize fields, it will not serialize properties (an indexer is a
property). This is for good reason because if a property gives access to
a field then you will serialize it elsewhere, and if it gives access to
data elsewhere (for example a database or a webservice) then that is a
different serialization issue.

Richard
 
Yes, ignore it. Take a cue from .NET serialization. It will only serialize
fields, it will not serialize properties (an indexer is a property).

Actually, .Net *will* serialize properties, as long as they have a get and a
set accessor method.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
A watched clock never boils.
 
XmlSerializer serializes public properties and fields.

I've spent a couple hours going through the code in reflector, but it's just
a nightmare to understand, largely because the XmlSerializer is creating
compiling the actual serializer into a "temporary" assembly which is then
executed. What I really need, is to see the code from the temporary assembly
so I can see how it works.

BTW, I put "temporary" in quotes because the assembly is generated in the
application's appdomain, so it can't be released until the AppDomain shuts
down.

Pete
 
Kevin said:
Actually, .Net *will* serialize properties, as long as they have a
get and a set accessor method.

Rubbish. Read up about serialization and learn how it works.

Apart from anything else, it makes no sense for properties to be
serialized. If you have a property that is based on a field then *two*
values will be serialized and that then raises the question of which
value will be used to 'initialize' the property. If the property is used
to calculate a value at runtime (for example, reads an item from a
database) then it will be dependent upon the actual time when the data
is read and serialization of such values makes no sense.

Just to prove that you are wrong, try this:

[Serializable]
public class DataItem
{
int data;
public int Data
{
get{return data;}
set{data=value;}
}
}

Then:

SoapFormatter sf = new SoapFormatter();
DataItem dataitem = new DataItem();
dataitem.Data = 42;
using (FileStream fs = File.OpenWrite("test.soap"))
{
sf.Serialize(fs, dataitem);
}

Run this code and view the file. You'll find an entry for DataItem.data,
and not for DataItem.Data:

<DataItem>
<data>42</data>
</DataItem>

Change DataItem to:

[Serializable]
public class DataItem
{
public int Data
{
get{return 42;}
set{Console::WriteLine("dont know what to do with {0}", value);}
}
}

Run the code again. You'll find no mention of Data.

You're wrong on this one, Kevin.

Richard
 
Pete said:
XmlSerializer serializes public properties and fields.

Yes. But it is not .NET runtime serialization :-)
I've spent a couple hours going through the code in reflector, but
it's just a nightmare to understand, largely because the
XmlSerializer is creating compiling the actual serializer into a
"temporary" assembly which is then executed. What I really need, is
to see the code from the temporary assembly so I can see how it works.

BTW, I put "temporary" in quotes because the assembly is generated in
the application's appdomain, so it can't be released until the
AppDomain shuts down.

It is actually saved to the user's temporary folder. When I tested this
out a while ago I put a FileSystemWatcher on (IIRC) %USERPROFILE%\Local
Settings\Temp and saw the generated assembly. I don't have the code at
hand but I think I implemented the event handler to copy the file to
another folder. To be honest I cannot remember whether it was
successful.

Richard
 
Richard said:
It is actually saved to the user's temporary folder. When I tested
this out a while ago I put a FileSystemWatcher on (IIRC)
%USERPROFILE%\Local Settings\Temp and saw the generated assembly. I
don't have the code at hand but I think I implemented the event
handler to copy the file to another folder. To be honest I cannot
remember whether it was successful.

Ah here it is, pretty rough and read, but it works:

using System;
using System.IO;

class App
{
static void Main()
{
string user = Environment.GetEnvironmentVariable("USERPROFILE");
user += @"\Local Settings\Temp";
FileSystemWatcher fsw = new FileSystemWatcher(user);
fsw.Created += new FileSystemEventHandler(newFile);
fsw.EnableRaisingEvents = true;
Console.WriteLine("press enter to finish");
Console.ReadLine();
fsw.EnableRaisingEvents = false;
fsw.Dispose();
}
// Make sure you create C:\temp
static void newFile(object o, FileSystemEventArgs args)
{
try
{
File.Copy(args.FullPath, @"C:\temp\" + args.Name);
}
catch{}
}
}

Its a bit hit and miss because the process calling XmlSerializer will
delete all the file when it has used them (I suspend the thread in the
code that calls XmlSerializer with another ReadLine so that the
XmlSerializer is not didposed before the watcher process has finished
copying file). On one run I got a .cs file, a zero length dll (obviously
it was deleted before I could completely copy it) and a .cmdline file
which was clearly the switches for the C# compiler

Richard
 
Back
Top