"Kevin Yu [MSFT]" <v-****@online.microsoft.com> wrote in message
news:6O**************@cpmsftngxa06.phx.gbl...
Hi John,
First of all, I would like to confirm my understanding of your issue. From
your description, I'm still not quite sure what you get. Do you mean that
adding a [XmlAttribute] on a property that returns TimeOfDay type will
make
the serialized data look bad?
Could you please paste some repro code here and show us the desired
result?
Thanks!
Here's a short console program that reproduces the problem followed by the
code for the TimeOfDay type.
using System;
using System.Xml.Serialization;
namespace XmlSample
{
/// <summary>
/// The Consumer class is just a simple example of a class that consumes
/// the TimeOfDay object. This is used to illustrate a problem with
XmlSerializer,
/// the StartTime property isn't serialized correctly. The real
question is:
///
/// What can be done to the TimeOfDay type to make XmlSerializer work?
///
/// </summary>
public class Consumer
{
public Consumer()
{
}
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public TimeOfDay StartTime
{
get
{
return m_StartTime;
}
set
{
m_StartTime = value;
}
}
//
// Private property backers
//
private string m_Name;
private TimeOfDay m_StartTime;
}
/// <summary>
/// Class1 contains the Main method.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// Create and populate a Consumer object
//
Consumer co = new Consumer();
co.Name = "John";
co.StartTime = new TimeOfDay("10:30");
//
// Create the XmlSerializer
//
XmlSerializer serializer = new XmlSerializer(co.GetType());
//
// Serialize!!
//
serializer.Serialize(Console.Out, co);
//
// Pause
//
Console.WriteLine();
Console.WriteLine("StartTime should be {0}", co.StartTime);
Console.WriteLine("Press Return to continue");
Console.ReadLine();
}
}
}
/////// TimeOfDay.cs
using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Xml.Serialization;
namespace XmlSample
{
/// <summary>
/// TimeOfDayConverter is a TypeConverter for the TimeOfDay type.
/// </summary>
public class TimeOfDayConverter : TypeConverter
{
/// <summary>
/// Returns true if the passed source Type can be converted into a
TimeOfDay.
/// </summary>
/// <param name="context"></param>
/// <param name="sourceType">THe Type to be converted.</param>
/// <returns>True if the conversion can be done.</returns>
public override bool CanConvertFrom(
ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
else
{
return base.CanConvertFrom(context, sourceType);
}
}
/// <summary>
/// Converts the passed value into a TimeOfDay.
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value">The value to convert into a
TimeOfDay.</param>
/// <returns>The new TimeOfDay.</returns>
public override object ConvertFrom(
ITypeDescriptorContext context, CultureInfo culture, object
value)
{
if (value is string)
{
return TimeOfDay.Parse((string)value);
}
else
{
return base.ConvertFrom(context, culture, value);
}
}
/// <summary>
/// Converts the passed TimeOfDay into the passed destination Type.
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value">The TimeOfDay</param>
/// <param name="destinationType">The destination Type</param>
/// <returns>The new object created from the TimeOfDay.</returns>
public override object ConvertTo(
ITypeDescriptorContext context, CultureInfo culture, object
value, Type destinationType)
{
if ((destinationType == typeof(string))
&& (value is TimeOfDay))
{
return
((TimeOfDay)value).ToString(culture.DateTimeFormat .ShortTimePattern);
}
else
{
return base.ConvertTo(context, culture, value,
destinationType);
}
}
}
/// <summary>
/// The TimeOfDay represents a time of day.
/// </summary>
[Serializable,
TypeConverter(typeof(TimeOfDayConverter)),
XmlType("time")]
public struct TimeOfDay : IComparable, IFormattable, ISerializable
{
private int timeOfDay; // The number of seconds since midnight (-1
means NULL)
/// <summary>
/// Constructs a TimeOfDay from an integer which is the seconds
since midnight.
/// </summary>
/// <param name="initial">The seconds since midnight.</param>
public TimeOfDay(int initial)
{
timeOfDay = initial;
}
/// <summary>
/// Constructs a TimeOfDay from a DateTime.
/// </summary>
/// <param name="initial">The DateTime to create the TimeOfDay
from.</param>
public TimeOfDay(DateTime initial)
{
timeOfDay = (int)(initial.TimeOfDay.Ticks /
TimeSpan.TicksPerSecond);
}
/// <summary>
/// Constructs a TimeOfDay from a string.
/// </summary>
/// <param name="initial">The string.</param>
public TimeOfDay(string initial)
{
DateTime tmpDT;
try
{
tmpDT = DateTime.Parse(initial);
timeOfDay = (int)(tmpDT.TimeOfDay.Ticks /
TimeSpan.TicksPerSecond);
}
catch
{
timeOfDay = -1;
}
}
/// <summary>
/// A TimeOfDay that is the current time.
/// </summary>
public static TimeOfDay Now
{
get
{
return new TimeOfDay(DateTime.Now);
}
}
// [XmlAttribute]
// public string value
// {
// get
// {
// if (timeOfDay < 0)
// {
// return null;
// }
// else
// {
// return "10:30";
// }
// }
// set
// {
// timeOfDay = -1;
// }
// }
/// <summary>
/// A TimeOfDay that represents a time that is not specified.
/// </summary>
public static TimeOfDay Empty
{
get
{
return new TimeOfDay(-1);
}
}
/// <summary>
/// Parse a formatted string and return it as a TimeOfDay
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static TimeOfDay Parse(string input)
{
DateTime tmpDT;
int ticks;
try
{
tmpDT = DateTime.Parse(input);
ticks = (int)(tmpDT.TimeOfDay.Ticks /
TimeSpan.TicksPerSecond);
}
catch
{
ticks = -1;
}
return new TimeOfDay(ticks);
}
/// <summary>
/// Compare two TimeOfDay objects.
/// </summary>
/// <param name="obj">The TimeOfDay to compare to.</param>
/// <returns>-1, 0 or 1.</returns>
public int CompareTo(object obj)
{
if (obj is TimeOfDay)
{
//
// We can do this
//
TimeOfDay otherTime = (TimeOfDay) obj;
return timeOfDay - otherTime.timeOfDay;
}
else
{
throw new ArgumentException();
}
}
/// <summary>
/// Compares two TimeOfDay objects to see if they represent the same
time.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
return (this.timeOfDay == ((TimeOfDay)obj).timeOfDay);
}
/// <summary>
/// Returns a hashcode for this time.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode ();
}
/// <summary>
/// Compare two times to see if the left is less than the right.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator <(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) < 0);
}
/// <summary>
/// Compare two times to see if the left is less than or equal to
the right.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator <=(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) <= 0);
}
/// <summary>
/// Compare two times to see if the left is greater than the right.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator >(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) > 0);
}
/// <summary>
/// Compare two times to see if the left is greater than or equal to
the right.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator >=(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) >= 0);
}
/// <summary>
/// Compare two times to see if they are equal.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator ==(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) == 0);
}
/// <summary>
/// Compare two times to see if they are not equal.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static bool operator !=(TimeOfDay left, TimeOfDay right)
{
return (left.CompareTo(right) != 0);
}
/// <summary>
/// Converts a TimeOfDay to a string.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return ToString(
CultureInfo.CurrentCulture.DateTimeFormat.ShortTim ePattern,
null);
}
/// <summary>
/// COnverts a TimeOfDay to a string using the specified
formatProvider.
/// </summary>
/// <param name="formatProvider"></param>
/// <returns></returns>
public string ToString(IFormatProvider formatProvider)
{
return ToString(
CultureInfo.CurrentCulture.DateTimeFormat.ShortTim ePattern,
formatProvider);
}
/// <summary>
/// COnverts a TimeOfDay to a string using the specified format.
/// </summary>
/// <param name="format"></param>
/// <returns></returns>
public string ToString(string format)
{
return ToString(format, null);
}
/// <summary>
/// Converts a TimeOfDay to a string using the specified format and
format provider.
/// </summary>
/// <param name="format"></param>
/// <param name="formatProvider"></param>
/// <returns></returns>
public string ToString(string format, IFormatProvider
formatProvider)
{
if ((timeOfDay < 0) || (timeOfDay >= 86400))
{
//
// The value is out of range
// We interpret this as a null time
//
return string.Empty;
}
else
{
//
// We have a valid value (number of seconds since midnight)
//
DateTime dtTmp = DateTime.Today;
dtTmp = dtTmp.AddSeconds(timeOfDay);
if (format == null)
{
return dtTmp.ToString(
CultureInfo.CurrentCulture.DateTimeFormat.ShortTim ePattern,
formatProvider);
}
else
{
return dtTmp.ToString(format, formatProvider);
}
}
}
/// <summary>
/// Returns a TimeSpan from midnight to the TimeOfDay
/// </summary>
/// <returns></returns>
public TimeSpan ToTimeSpan()
{
if (timeOfDay >= 0)
{
return new TimeSpan((TimeSpan.TicksPerSecond * timeOfDay));
}
else
{
return new TimeSpan(0);
}
}
/// <summary>
/// Returns the seconds between midnight and the time of day.
/// </summary>
public int TotalSeconds
{
get
{
return timeOfDay;
}
}
#region Implementation of ISerializable
//
// Code generated by BuildISerializable
//
/// <summary>
/// Deserialization constructor.
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
private TimeOfDay(SerializationInfo info, StreamingContext context)
{
timeOfDay = info.GetInt32("timeOfDay");
}
/// <summary>
/// Serializes a TimeOfDay.
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
// An unknown external module throws a SEHException when this line
is uncommented
//[SecurityPermission(SecurityAction.Demand,
SerializationFormatter=true)]
public void GetObjectData(SerializationInfo info, StreamingContext
context)
{
info.AddValue("timeOfDay", timeOfDay);
}
#endregion
}
}