Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API Proposal]: Add methods which works with Guid/TimeSpan in System.Xml.XmlWriter/XmlReader #75515

Open
TrayanZapryanov opened this issue Sep 13, 2022 · 19 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Xml
Milestone

Comments

@TrayanZapryanov
Copy link
Contributor

TrayanZapryanov commented Sep 13, 2022

Background and motivation

Reading and writing Guids and TimeSpans in xml is quire normal practice these days.
We should allow users to read or write these primitive types instead of using existing ones based on string or object.

API Proposal

namespace System.Xml;

public class XmlWriter
{
    public virtual void WriteValue(Guid value);
    public virtual void WriteValue(TimeSpan value);
}

public class XmlReader
{
    public virtual Guid ReadContentAsGuid();
    public virtual Guid ReadElementContentAsGuid();

    public virtual TimeSpan ReadContentAsTimeSpan();
    public virtual TimeSpan ReadElementContentAsTimeSpan();
}

API Usage

XmlWriter writer;
writer.WriteValue(Guid.NewGuid());
writer.WriteValue(TimeSpan.FromHours(1));

XmlReader reader;
Guid g = reader.ReadContentAsGuid();
TimeSpan t = reader.ReadContentAsTimeSpan();

Alternative Designs

We can make these methods internal and use them only in System.Private.Xml project.

Risks

none

@TrayanZapryanov TrayanZapryanov added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Sep 13, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 13, 2022
@ghost
Copy link

ghost commented Sep 13, 2022

Tagging subscribers to this area: @dotnet/area-system-xml
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and motivation

Writing Guids and TimeSpans in xml is quire normal practice these days. We should allow users to use it instead of casting them to sring and then using WriteValue(string) method or using WriteValue(object).

API Proposal

namespace System.Xml;

public class XmlWriter
{
    public virtual void WriteValue(Guid value);
    public virtual void WriteValue(TimeSpan value);
}

API Usage

XmlWriter writer;
writer.WriteValue(Guid.NewGuid());
writer.WriteValue(TimeSpan.FromHours(1));

Alternative Designs

We can make these methods internal and use them only in System.Private.Xml project.

Risks

none

Author: TrayanZapryanov
Assignees: -
Labels:

api-suggestion, area-System.Xml

Milestone: -

@eiriktsarpalis
Copy link
Member

We should allow users to use it instead of casting them to sring and then using WriteValue(string) method or using WriteValue(object).

Perhaps we could simply add a WriteValue(ReadOnlySpan<char>) overload?

@TrayanZapryanov
Copy link
Contributor Author

We should allow users to use it instead of casting them to sring and then using WriteValue(string) method or using WriteValue(object).

Perhaps we could simply add a WriteValue(ReadOnlySpan<char>) overload?

Not exactly as we want to format things in a specific way . For example Timespan is serialized like this right now :

public static string ToString(TimeSpan value)
  {
      return new XsdDuration(value).ToString();
  }

@eiriktsarpalis
Copy link
Member

Both TimeSpan and Guid expose TryFormat methods that can be used to format into a span destination. A ReadOnlySpan overload should help unlock allocation-free formatting for arbitrary types.

@TrayanZapryanov
Copy link
Contributor Author

@eiriktsarpalis I agree, just the clients should have some internal knowledge.
Instead of calling writer.WriteValue(TimeSpan.FromHours(1))
they should call

new XsdDuration(value).TryFormat(someSpan)
writer.WriteValue(someSpan)

@drieseng
Copy link
Contributor

Personally, I see good use for these proposed overloads (and I'd even add overloads for DateOnly and TimeOnly).

@eiriktsarpalis
Copy link
Member

I have no strong opinion on adding TimeSpan or Guid overloads. For parity, the API proposal should contain equivalent overloads in XmlReader, the proposal needs updating to include them as well.

@krwq do you think they're worth adding?

@TahirAhmadov
Copy link

TahirAhmadov commented Sep 16, 2022

I would just add that the format of TimeSpan, and especially DateOnly and even perhaps DateTime, has to be carefully chosen to ensure it works across all possible values. I'm thinking it has to be "cultureless" to work.
PS. For Guid, it's not that complicated, but still, even if we say that XmlWriter should write the standard "dashed" format, the XmlReader should be able to interpret both the "dashed" and the "N" format, in case XML is generated by something other than .NET or is user modified.

@TrayanZapryanov
Copy link
Contributor Author

Main benefit will be in writing Guids in XmlWriter as we will save Guid.ToString() allocation.
If you like I can remove TimeSpan as I do not expect too many TimeSpans serializations.
I've added it as it is tricky and current implementation uses XsdDuration.ToString().

@eiriktsarpalis
Copy link
Member

@TrayanZapryanov would it be possible to update the API proposal in the OP to include XmlReader equivalents?

@eiriktsarpalis eiriktsarpalis removed the untriaged New issue has not been triaged by the area owner label Sep 20, 2022
@eiriktsarpalis eiriktsarpalis added this to the Future milestone Sep 20, 2022
@TrayanZapryanov TrayanZapryanov changed the title [API Proposal]: Add WriteValue(Guid/TimeSpan) in System.Xml.XmlWriter [API Proposal]: Add WriteValue(Guid/TimeSpan) in System.Xml.XmlWriter/XmlReader Sep 20, 2022
@TrayanZapryanov
Copy link
Contributor Author

@eiriktsarpalis Done.

@TrayanZapryanov TrayanZapryanov changed the title [API Proposal]: Add WriteValue(Guid/TimeSpan) in System.Xml.XmlWriter/XmlReader [API Proposal]: Add methods which works with Guid/TimeSpan in System.Xml.XmlWriter/XmlReader Sep 20, 2022
@eiriktsarpalis
Copy link
Member

Thanks. I'm deferring to @krwq on whether to mark this as api-ready-for-review as he is the subject matter expert of this codebase.

@TrayanZapryanov
Copy link
Contributor Author

Small risk that I've found right now:
Imagine code which is using XmlWriter.WriteValue(Guid.NewGuid()) - this will fallback to XmlWriter.WriteValue(object) if not overridden. Current implementation of it is using :

// Writes out the specified value.
  public virtual void WriteValue(object value)
  {
      ArgumentNullException.ThrowIfNull(value);

      WriteString(XmlUntypedConverter.Untyped.ToString(value, null));
  }

and as XmlUntypedConverter.Untyped.ToString(value, null) is not supporting Guid - it will throw exception.
With proposed change - this will be accepted or in the base class we need to throw same exception.
I would prefer to accept and fallback to something like this :

// Writes out the specified value.
  public virtual void WriteValue(Guid value)
  {
      WriteString(XmlConvert.ToString(value));
  }

@TrayanZapryanov
Copy link
Contributor Author

One more note:
According Help documentation, WriteValue methods should map CLR types defined also in Xsd(or this is what I understand). So Guid is somehow "custom" and maybe should be skipped, but at least TimeSpan can be mapped to "time" : XSD Date and Time Data Types.

@krwq
Copy link
Member

krwq commented Sep 27, 2022

I'm curious - do we actually care about XmlReader APIs or we just want XmlSerializer work with those? Are you actually using reader/writer directly?

@TrayanZapryanov
Copy link
Contributor Author

@krwq Nope, I am not using them. Proposal is just to use them when serializing primitive types in XmlSerializer.

@krwq
Copy link
Member

krwq commented Sep 29, 2022

I think we should start with trying to handle that in XmlSerializer directly and only add APIs to XmlReader/XmlWriter if there is clear benefit

@TrayanZapryanov
Copy link
Contributor Author

@krwq You are right. I've added new performance issue.
Should I close this proposal or you see some benefit in implementing it ?

@krwq
Copy link
Member

krwq commented Oct 3, 2022

I'm not the owner of serialization part of the XML but I'd suggest running profiler with some real-life like payload and seeing if making a fix makes any difference. If there is clear difference then you already got prototype 😄 if change is relatively simple might be still worth to send a patch - I'd personally only do it if my particular scenario I'm trying to improve requires it (i.e. I have app which I'm trying to improve and profiler tells me this has huge impact on it or I'm particularly focusing on allocations/perf in XML)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Xml
Projects
None yet
Development

No branches or pull requests

5 participants