| File: System\ServiceModel\Channels\BodyWriter.cs | Web Access |
| Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Threading.Tasks; using System.Xml; namespace System.ServiceModel.Channels { public abstract class BodyWriter { private bool _canWrite; private object _thisLock; protected BodyWriter(bool isBuffered) { IsBuffered = isBuffered; _canWrite = true; if (!IsBuffered) { _thisLock = new object(); } } public bool IsBuffered { get; } internal virtual bool IsEmpty { get { return false; } } internal virtual bool IsFault { get { return false; } } public BodyWriter CreateBufferedCopy(int maxBufferSize) { if (maxBufferSize < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxBufferSize), maxBufferSize, SRP.ValueMustBeNonNegative)); } if (IsBuffered) { return this; } else { lock (_thisLock) { if (!_canWrite) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.BodyWriterCanOnlyBeWrittenOnce)); } _canWrite = false; } BodyWriter bodyWriter = OnCreateBufferedCopy(maxBufferSize); if (!bodyWriter.IsBuffered) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.BodyWriterReturnedIsNotBuffered)); } return bodyWriter; } } protected virtual BodyWriter OnCreateBufferedCopy(int maxBufferSize) { return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max); } internal BodyWriter OnCreateBufferedCopy(int maxBufferSize, XmlDictionaryReaderQuotas quotas) { XmlBuffer buffer = new XmlBuffer(maxBufferSize); using (XmlDictionaryWriter writer = buffer.OpenSection(quotas)) { writer.WriteStartElement("a"); OnWriteBodyContents(writer); writer.WriteEndElement(); } buffer.CloseSection(); buffer.Close(); return new BufferedBodyWriter(buffer); } protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer); protected virtual Task OnWriteBodyContentsAsync(XmlDictionaryWriter writer) { OnWriteBodyContents(writer); return Task.CompletedTask; } protected virtual IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state) { throw ExceptionHelper.PlatformNotSupported(); } protected virtual void OnEndWriteBodyContents(IAsyncResult result) { throw ExceptionHelper.PlatformNotSupported(); } private void EnsureWriteBodyContentsState(XmlDictionaryWriter writer) { if (writer == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(writer))); } if (!IsBuffered) { lock (_thisLock) { if (!_canWrite) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.BodyWriterCanOnlyBeWrittenOnce)); } _canWrite = false; } } } public void WriteBodyContents(XmlDictionaryWriter writer) { EnsureWriteBodyContentsState(writer); OnWriteBodyContents(writer); } internal Task WriteBodyContentsAsync(XmlDictionaryWriter writer) { EnsureWriteBodyContentsState(writer); return OnWriteBodyContentsAsync(writer); } public IAsyncResult BeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state) { EnsureWriteBodyContentsState(writer); return OnBeginWriteBodyContents(writer, callback, state); } public void EndWriteBodyContents(IAsyncResult result) { OnEndWriteBodyContents(result); } internal class BufferedBodyWriter : BodyWriter { private XmlBuffer _buffer; public BufferedBodyWriter(XmlBuffer buffer) : base(true) { _buffer = buffer; } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { XmlDictionaryReader reader = _buffer.GetReader(0); using (reader) { reader.ReadStartElement(); while (reader.NodeType != XmlNodeType.EndElement) { writer.WriteNode(reader, false); } reader.ReadEndElement(); } } } } }