Description
Background and motivation
The abstract XmlReader
class has been around since the beginning of .NET, and it is foundational to System.Xml.Linq among others.
One problem is that all async methods on XmlReader
is missing CancellationToken
parameters. For example, this causes the cancellation token used in XDocument.LoadAsync
to not be respected (#114555).
The new methods could also have ValueTask
return types, but I opted for regular Task
s in this proposal for simplicity.
The System.Xml
namespace has many synchronous methods that are missing asynchronous counterparts, but they are not considered in this proposal.
API Proposal
namespace System.Xml
public class XmlReader
{
public virtual System.Threading.Tasks.Task<string> GetValueAsync();
+ public virtual System.Threading.Tasks.Task<string> GetValueAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<bool> ReadAsync();
+ public virtual System.Threading.Tasks.Task<bool> ReadAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<object> ReadContentAsAsync(Type returnType, System.Xml.IXmlNamespaceResolver? namespaceResolver);
+ public virtual System.Threading.Tasks.Task<object> ReadContentAsAsync(Type returnType, System.Xml.IXmlNamespaceResolver? namespaceResolver, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<int> ReadContentAsBase64Async(byte[] buffer, int index, int count);
+ public virtual System.Threading.Tasks.Task<int> ReadContentAsBase64Async(byte[] buffer, int index, int count, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<int> ReadContentAsBinHexAsync(byte[] buffer, int index, int count);
+ public virtual System.Threading.Tasks.Task<int> ReadContentAsBinHexAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<object> ReadContentAsObjectAsync();
+ public virtual System.Threading.Tasks.Task<object> ReadContentAsObjectAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<string> ReadContentAsStringAsync();
+ public virtual System.Threading.Tasks.Task<string> ReadContentAsStringAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<object> ReadElementContentAsAsync(Type returnType, System.Xml.IXmlNamespaceResolver namespaceResolver);
+ public virtual System.Threading.Tasks.Task<object> ReadElementContentAsAsync(Type returnType, System.Xml.IXmlNamespaceResolver namespaceResolver, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<int> ReadElementContentAsBase64Async(byte[] buffer, int index, int count);
+ public virtual System.Threading.Tasks.Task<int> ReadElementContentAsBase64Async(byte[] buffer, int index, int count, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<int> ReadElementContentAsBinHexAsync(byte[] buffer, int index, int count);
+ public virtual System.Threading.Tasks.Task<int> ReadElementContentAsBinHexAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<object> ReadElementContentAsObjectAsync();
+ public virtual System.Threading.Tasks.Task<object> ReadElementContentAsObjectAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<string> ReadElementContentAsStringAsync();
+ public virtual System.Threading.Tasks.Task<string> ReadElementContentAsStringAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<string> ReadInnerXmlAsync();
+ public virtual System.Threading.Tasks.Task<string> ReadInnerXmlAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<string> ReadOuterXmlAsync();
+ public virtual System.Threading.Tasks.Task<string> ReadOuterXmlAsync(CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task<int> ReadValueChunkAsync(char[] buffer, int index, int count);
+ public virtual System.Threading.Tasks.Task<int> ReadValueChunkAsync(char[] buffer, int index, int count, CancellationToken cancellationToken);
public virtual System.Threading.Tasks.Task SkipAsync();
+ public virtual System.Threading.Tasks.Task SkipAsync(CancellationToken cancellationToken);
}
API Usage
// Fancy the value
var c = new MyFancyCollection<int>();
c.Fancy(42);
// Getting the values out
foreach (var v in c)
Console.WriteLine(v);
Alternative Designs
No response
Risks
Default implementation of virtual methpos ReadAsync
and GetValueAsync
simply throws NotImplementedException
, kind of like "optional" abstract methods I intepret it like.
All async-supporting, built-in classes deriving from XmlReader
(i.e. XmlTextReader
etc.) should have the overrides for these new methods added as part of this change.
But it might be unclear how this change would affect custom subclasses for XmlReader that for example would override ReadAsync()
but not ReadAsync(CancellationToken)
.