#if !CORECLR /********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System; using System.Diagnostics; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.IO; using System.Transactions; using System.Threading; using System.Collections.Generic; using System.Text; namespace Microsoft.PowerShell.Commands.Management { /// /// Represents a a string that can be used in transactions. /// public class TransactedString : IEnlistmentNotification { StringBuilder m_Value; StringBuilder m_TemporaryValue; Transaction enlistedTransaction = null; /// /// Constructor for the TransactedString class. /// public TransactedString() : this("") { } /// /// Constructor for the TransactedString class. /// /// /// The initial value of the transacted string. /// /// public TransactedString(string value) { m_Value = new StringBuilder(value); m_TemporaryValue = null; } /// /// Make the transacted changes permanent. /// void IEnlistmentNotification.Commit(Enlistment enlistment) { m_Value = new StringBuilder(m_TemporaryValue.ToString()); m_TemporaryValue = null; enlistedTransaction = null; enlistment.Done(); } /// /// Discard the transacted changes. /// void IEnlistmentNotification.Rollback(Enlistment enlistment) { m_TemporaryValue = null; enlistedTransaction = null; enlistment.Done(); } /// /// Discard the transacted changes. /// void IEnlistmentNotification.InDoubt(Enlistment enlistment) { enlistment.Done(); } void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } /// /// Append text to the transacted string. /// /// /// The text to append. /// /// public void Append(string text) { ValidateTransactionOrEnlist(); if(enlistedTransaction != null) { m_TemporaryValue.Append(text); } else { m_Value.Append(text); } } /// /// Remove text from the transacted string. /// /// /// The position in the string from which to start removing. /// /// /// The length of text to remove. /// /// public void Remove(int startIndex, int length) { ValidateTransactionOrEnlist(); if(enlistedTransaction != null) { m_TemporaryValue.Remove(startIndex, length); } else { m_Value.Remove(startIndex, length); } } /// /// Gets the length of the transacted string. If this is /// called within the transaction, it returns the length of /// the transacted value. Otherwise, it returns the length of /// the original value. /// public int Length { get { // If we're not in a transaction, or we are in a different transaction than the one we // enlisted to, return the publicly visible state. if( (Transaction.Current == null) || (enlistedTransaction != Transaction.Current)) { return m_Value.Length; } else { return m_TemporaryValue.Length; } } } /// /// Gets the System.String that represents the transacted /// transacted string. If this is called within the /// transaction, it returns the transacted value. /// Otherwise, it returns the original value. /// public override string ToString() { // If we're not in a transaction, or we are in a different transaction than the one we // enlisted to, return the publicly visible state. if( (Transaction.Current == null) || (enlistedTransaction != Transaction.Current)) { return m_Value.ToString(); } else { return m_TemporaryValue.ToString(); } } private void ValidateTransactionOrEnlist() { // We're in a transaction if(Transaction.Current != null) { // We haven't yet been called inside of a transaction. So enlist // in the transaction, and store our save point if(enlistedTransaction == null) { Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None); enlistedTransaction = Transaction.Current; m_TemporaryValue = new StringBuilder(m_Value.ToString()); } // We're already enlisted in a transaction else { // And we're in that transaction if(Transaction.Current != enlistedTransaction) { throw new InvalidOperationException("Cannot modify string. It has been modified by another transaction."); } } } // We're not in a transaction else { // If we're not subscribed to a transaction, modify the underlying value if(enlistedTransaction != null) { throw new InvalidOperationException("Cannot modify string. It has been modified by another transaction."); } } } } } // namespace Microsoft.Test.Management.Automation #endif