MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Text;6using System.Transactions;7 8namespace Microsoft.PowerShell.Commands.Management9{10 /// <summary>11 /// Represents a string that can be used in transactions.12 /// </summary>13 public class TransactedString : IEnlistmentNotification14 {15 private StringBuilder _value;16 private StringBuilder _temporaryValue;17 private Transaction _enlistedTransaction = null;18 19 /// <summary>20 /// Constructor for the TransactedString class.21 /// </summary>22 public TransactedString() : this(string.Empty)23 {24 }25 26 /// <summary>27 /// Constructor for the TransactedString class.28 /// </summary>29 /// <param name="value">30 /// The initial value of the transacted string.31 /// </param>32 public TransactedString(string value)33 {34 _value = new StringBuilder(value);35 _temporaryValue = null;36 }37 38 /// <summary>39 /// Make the transacted changes permanent.40 /// </summary>41 void IEnlistmentNotification.Commit(Enlistment enlistment)42 {43 _value = new StringBuilder(_temporaryValue.ToString());44 _temporaryValue = null;45 _enlistedTransaction = null;46 enlistment.Done();47 }48 49 /// <summary>50 /// Discard the transacted changes.51 /// </summary>52 void IEnlistmentNotification.Rollback(Enlistment enlistment)53 {54 _temporaryValue = null;55 _enlistedTransaction = null;56 enlistment.Done();57 }58 59 /// <summary>60 /// Discard the transacted changes.61 /// </summary>62 void IEnlistmentNotification.InDoubt(Enlistment enlistment)63 {64 enlistment.Done();65 }66 67 void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment)68 {69 preparingEnlistment.Prepared();70 }71 72 /// <summary>73 /// Append text to the transacted string.74 /// </summary>75 /// <param name="text">76 /// The text to append.77 /// </param>78 public void Append(string text)79 {80 ValidateTransactionOrEnlist();81 82 if (_enlistedTransaction != null)83 {84 _temporaryValue.Append(text);85 }86 else87 {88 _value.Append(text);89 }90 }91 92 /// <summary>93 /// Remove text from the transacted string.94 /// </summary>95 /// <param name="startIndex">96 /// The position in the string from which to start removing.97 /// </param>98 /// <param name="length">99 /// The length of text to remove.100 /// </param>101 public void Remove(int startIndex, int length)102 {103 ValidateTransactionOrEnlist();104 105 if (_enlistedTransaction != null)106 {107 _temporaryValue.Remove(startIndex, length);108 }109 else110 {111 _value.Remove(startIndex, length);112 }113 }114 115 /// <summary>116 /// Gets the length of the transacted string. If this is117 /// called within the transaction, it returns the length of118 /// the transacted value. Otherwise, it returns the length of119 /// the original value.120 /// </summary>121 public int Length122 {123 get124 {125 // If we're not in a transaction, or we are in a different transaction than the one we126 // enlisted to, return the publicly visible state.127 if (128 (Transaction.Current == null) ||129 (_enlistedTransaction != Transaction.Current))130 {131 return _value.Length;132 }133 else134 {135 return _temporaryValue.Length;136 }137 }138 }139 140 /// <summary>141 /// Gets the System.String that represents the transacted142 /// transacted string. If this is called within the143 /// transaction, it returns the transacted value.144 /// Otherwise, it returns the original value.145 /// </summary>146 public override string ToString()147 {148 // If we're not in a transaction, or we are in a different transaction than the one we149 // enlisted to, return the publicly visible state.150 if (151 (Transaction.Current == null) ||152 (_enlistedTransaction != Transaction.Current))153 {154 return _value.ToString();155 }156 else157 {158 return _temporaryValue.ToString();159 }160 }161 162 private void ValidateTransactionOrEnlist()163 {164 // We're in a transaction165 if (Transaction.Current != null)166 {167 // We haven't yet been called inside of a transaction. So enlist168 // in the transaction, and store our save point169 if (_enlistedTransaction == null)170 {171 Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None);172 _enlistedTransaction = Transaction.Current;173 174 _temporaryValue = new StringBuilder(_value.ToString());175 }176 // We're already enlisted in a transaction177 else178 {179 // And we're in that transaction180 if (Transaction.Current != _enlistedTransaction)181 {182 throw new InvalidOperationException("Cannot modify string. It has been modified by another transaction.");183 }184 }185 }186 // We're not in a transaction187 else188 {189 // If we're not subscribed to a transaction, modify the underlying value190 if (_enlistedTransaction != null)191 {192 throw new InvalidOperationException("Cannot modify string. It has been modified by another transaction.");193 }194 }195 }196 }197}198 