/// <summary> /// Adds the well-known <abbr title="document type definition">DTD</abbr> that is defined in XHTML 1.1 /// to the <see cref="XmlPreloadedResolver"/> store. /// This DTD is already cached and embedded in the current assembly, so no network connections are required. /// </summary> /// <param name="resolver">The resolver to which to add the DTD for XHTML 1.1.</param> /// <param name="override"> /// Whether to add the DTD and override the mappings for the URIs associated with XHTML 1.1 if they are already defined in the store. /// This can happen if the DTD for XHTML 1.1 is included by default in the <see cref="XmlPreloadedResolver"/> class /// in future or alternative implementations of the .NET Framework, /// or if the said DTD has already been added manually to the <paramref name="resolver"/> instance. /// </param> /// <returns> /// <see langword="true"/> if the DTD was added to the store and mapped to at least one of its URIs; /// <see langword="false"/> if both URIs were already defined and not overridden. /// </returns> /// <remarks> /// <para> /// The <see cref="XmlPreloadedResolver"/> class is preloaded by default with DTDs defined in XHTML 1.0 and RSS 0.91, /// but has not been updated to include XHTML 1.1 as of .NET Framework 4.6.1. /// Per the reference source for the <see href="http://referencesource.microsoft.com/#System.Xml/System/Xml/Resolvers/XmlPreloadedResolver.cs,33dd036cf1a84ad9">AddKnownDtd</see> /// private method of the <see cref="XmlPreloadedResolver"/> class, the default DTDs are mapped to both their public and their system identifiers. /// In the same vein, this method maps the DTD for XHTML 1.1 to its public identifier, <see cref="Xhtml11.DtdPublicId"/>, /// as well as to its system identifier, <see cref="Xhtml11.DtdSystemId"/>. /// </para> /// <para> /// The flattened version of the DTD for XHTML 1.1, which is embedded in the current assembly, /// is available at <see href="https://www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd">xhtml11-flat.dtd</see> /// on the W3C website. /// </para> /// <list type="bullet"> /// <listheader>References</listheader> /// <item><see href="https://en.wikipedia.org/wiki/XML_Catalog">XML Catalog</see>, <i>Wikipedia</i></item> /// <item><see href="http://stackoverflow.com/q/1645767/1149773">How do I resolve entities when loading into an XDocument?"</see>, <i>Stack Overflow</i></item> /// <item><see href="http://stackoverflow.com/q/3733255/1149773">How to speed up loading DTD through DOCTYPE</see>, <i>Stack Overflow</i></item> /// </list> /// </remarks> /// <example> /// <code> /// var xmlResolver = new XmlPreloadedResolver(); /// xmlResolver.AddXhtml11(); /// /// XmlReaderSettings settings = new XmlReaderSettings(); /// settings.DtdProcessing = DtdProcessing.Parse; /// settings.XmlResolver = xmlResolver; /// /// XDocument document; /// using (var xmlReader = XmlReader.Create(input, settings)) /// document = XDocument.Load(xmlReader); /// </code> /// </example> public static void AddXhtml11(this XmlPreloadedResolver resolver, bool @override = false) { ArgumentValidate.NotNull(resolver, nameof(resolver)); Add(resolver, new Uri(Xhtml11.DtdPublicId, UriKind.RelativeOrAbsolute), ManifestResources.Xhtml11FlatDtdBytes, @override); Add(resolver, new Uri(Xhtml11.DtdSystemId, UriKind.RelativeOrAbsolute), ManifestResources.Xhtml11FlatDtdBytes, @override); }
/// <summary> /// Reports the zero-based index of the first occurrence of the specified value in the sequence, /// using the specified equality comparer to compare it with the sequence's elements. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">The sequence that contains the elements to search through.</param> /// <param name="value">The value to search for.</param> /// <param name="comparer">An <see cref="IEqualityComparer{T}"/> to compare values.</param> /// <returns> /// The zero-based index position of the first occurrence of an element in <paramref name="source"/> /// that is equal to <paramref name="value"/>, if found; /// or -1 if <paramref name="source"/> is empty or no match is found. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="source"/> or <paramref name="comparer"/> is <see langword="null"/>. /// </exception> public static int IndexOf <TSource>(this IEnumerable <TSource> source, TSource value, IEqualityComparer <TSource> comparer) { ArgumentValidate.NotNull(source, nameof(source)); ArgumentValidate.NotNull(comparer, nameof(comparer)); return(source.IndexOf(element => comparer.Equals(element, value))); }
/// <summary> /// Transforms the asynchronous function delegate to deliver all exceptions asynchronously, /// through the returned <see cref="Task{TResult}"/>. /// This includes exceptions thrown from the synchronous part of the original asynchronous delegate, /// which would otherwise be thrown directly to the caller as soon as the delegate is invoked. /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the delegate.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the delegate.</typeparam> /// <typeparam name="T6">The type of the sixth parameter of the delegate.</typeparam> /// <typeparam name="T7">The type of the seventh parameter of the delegate.</typeparam> /// <typeparam name="T8">The type of the eighth parameter of the delegate.</typeparam> /// <typeparam name="T9">The type of the ninth parameter of the delegate.</typeparam> /// <typeparam name="T10">The type of the tenth parameter of the delegate.</typeparam> /// <typeparam name="T11">The type of the eleventh parameter of the delegate.</typeparam> /// <typeparam name="T12">The type of the twelfth parameter of the delegate.</typeparam> /// <typeparam name="T13">The type of the thirteenth parameter of the delegate.</typeparam> /// <typeparam name="T14">The type of the fourteenth parameter of the delegate.</typeparam> /// <typeparam name="T15">The type of the fifteenth parameter of the delegate.</typeparam> /// <typeparam name="T16">The type of the sixteenth parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="asyncFunc">The asynchronous function delegate to be transformed.</param> /// <returns>The asynchronous function delegate encapsulating <paramref name="asyncFunc"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="asyncFunc"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="AsyncActionExtensions.DeliverAsync(Func{Task})"/> extension method. /// </remarks> public static Func <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, Task <TResult> > DeliverAsync <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(this Func <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, Task <TResult> > asyncFunc) { ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); return(async(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) => await asyncFunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16).ConfigureAwait(false)); }
/// <summary> /// Verifies that an exception of type <see cref="AssertFailedException"/> /// is thrown during the execution of <paramref name="action"/>. /// The assertion fails if no uncaught exception is thrown, /// of if another type of exception is thrown. /// </summary> /// <param name="action">The action delegate that should throw the exception.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> /// <returns>The exception that was thrown by <paramref name="action"/>.</returns> /// <example> /// This method is useful for writing unit tests to verify the implementation of methods in custom <c>…Assert</c> classes. /// For example, it is used for testing the <see cref="EnumerableAssert"/> class implemented in this library. /// <code> /// ExceptionAssert.ThrowsAssertFailed(() => Assert.Fail()); /// ExceptionAssert.ThrowsAssertFailed(() => Assert.AreEqual(16, 32)); /// </code> /// </example> public static AssertFailedException ThrowsAssertFailed(Action action, string message = null) { ArgumentValidate.NotNull(action, nameof(action)); // Could call ThrowsInner instead to customize messages. return(Throws <AssertFailedException>(action, message)); }
/// <summary> /// Transforms the asynchronous function delegate to deliver all exceptions asynchronously, /// through the returned <see cref="Task{TResult}"/>. /// This includes exceptions thrown from the synchronous part of the original asynchronous delegate, /// which would otherwise be thrown directly to the caller as soon as the delegate is invoked. /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="asyncFunc">The asynchronous function delegate to be transformed.</param> /// <returns>The asynchronous function delegate encapsulating <paramref name="asyncFunc"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="asyncFunc"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="AsyncActionExtensions.DeliverAsync(Func{Task})"/> extension method. /// </remarks> public static Func <T1, T2, Task <TResult> > DeliverAsync <T1, T2, TResult>(this Func <T1, T2, Task <TResult> > asyncFunc) { ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); return(async(T1 arg1, T2 arg2) => await asyncFunc(arg1, arg2).ConfigureAwait(false)); }
/// <summary> /// Converts the specified hexadecimal string to an equivalent byte array of 8-bit unsigned integers. /// </summary> /// <param name="hex">The source hexadecimal string to convert.</param> /// <returns>A byte array of 8-bit unsigned integers that is equivalent to <paramref name="hex"/>.</returns> /// <remarks> /// <para> /// Both uppercase (<c>'A'</c> to <c>'F'</c>) and lowercase (<c>'a'</c> to <c>'f'</c>) hexadecimal characters are allowed. /// Since each hexadecimal character represents a nibble (four bits), /// a <i>pair</i> of hexadecimal characters is required to represent a byte (eight bits). /// For this reason, the source string must have an even number of characters; /// see <see href="http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa/24343727#comment2392703_311179">Stack Overflow comment</see>. /// </para> /// <para> /// This method implementation uses a <see href="https://en.wikipedia.org/wiki/Lookup_table">lookup table</see>. /// Refer to the remarks on the <see cref="ToHexadecimal"/> method for a performance discussion. /// Whilst <see cref="ToHexadecimal"/> performs lookups on a per-byte level, /// this methods does so on a per-nibble level. /// </para> /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="hex"/> is <see langword="null"/>.</exception> /// <exception cref="FormatException"> /// The source string does not have an even number of characters. -or- /// The source string contains non-hexadecimal characters. /// </exception> public static byte[] FromHexadecimal(string hex) { ArgumentValidate.NotNull(hex, nameof(hex)); if (hex.Length % 2 != 0) { throw new FormatException("The source string must have an even number of characters."); } byte[] result = new byte[hex.Length / 2]; for (int i = 0; i < result.Length; i++) { char hiChar = hex[i * 2]; char loChar = hex[i * 2 + 1]; if (hiChar > 'f' || loChar > 'f') { throw new FormatException("The source string contains non-hexadecimal characters."); } byte hi = hexValues[hiChar]; byte lo = hexValues[loChar]; if (hi == 255 || lo == 255) { throw new FormatException("The source string contains non-hexadecimal characters."); } result[i] = (byte)((hi << 4) | lo); } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="KeyComparer{TSource, TKey}"/> class, /// using the specified key extraction function and the specified or default /// sort-order comparer for extracted keys. /// </summary> /// <param name="keySelector">A function to extract the key from a source item.</param> /// <param name="innerComparer"> /// The sort-order comparison operation to apply to the extracted keys. /// If the argument is omitted or specified as <see langword="null"/>, /// the <see cref="Comparer{T}.Default"/> comparer for type <typeparamref name="TKey"/> is used. /// </param> /// <exception cref="ArgumentNullException"><paramref name="keySelector"/> is <see langword="null"/>.</exception> protected internal KeyComparer(Func <TSource, TKey> keySelector, IComparer <TKey> innerComparer = null) { ArgumentValidate.NotNull(keySelector, nameof(keySelector)); _keySelector = keySelector; _innerComparer = innerComparer ?? Comparer <TKey> .Default; }
/// <summary> /// Sets the culture used by the current thread to the <paramref name="culture"/> instance, /// and creates an <see cref="IDisposable"/> that restores the former culture when /// its <see cref="IDisposable.Dispose()"/> method is called. /// </summary> /// <param name="culture">The culture to set for the lifetime of this instance.</param> /// <exception cref="ArgumentNullException"><paramref name="culture"/> is <see langword="null"/>.</exception> public CultureSwapper(CultureInfo culture) { ArgumentValidate.NotNull(culture, nameof(culture)); formerCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = culture; }
/// <summary> /// Transforms the asynchronous function delegate to deliver all exceptions asynchronously, /// through the returned <see cref="Task{TResult}"/>. /// This includes exceptions thrown from the synchronous part of the original asynchronous delegate, /// which would otherwise be thrown directly to the caller as soon as the delegate is invoked. /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the delegate.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the delegate.</typeparam> /// <typeparam name="T6">The type of the sixth parameter of the delegate.</typeparam> /// <typeparam name="T7">The type of the seventh parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="asyncFunc">The asynchronous function delegate to be transformed.</param> /// <returns>The asynchronous function delegate encapsulating <paramref name="asyncFunc"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="asyncFunc"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="AsyncActionExtensions.DeliverAsync(Func{Task})"/> extension method. /// </remarks> public static Func <T1, T2, T3, T4, T5, T6, T7, Task <TResult> > DeliverAsync <T1, T2, T3, T4, T5, T6, T7, TResult>(this Func <T1, T2, T3, T4, T5, T6, T7, Task <TResult> > asyncFunc) { ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); return(async(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) => await asyncFunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7).ConfigureAwait(false)); }
/// <summary> /// Initializes a new instance of the <see cref="EnumeratorPair{T}"/> class /// that iterates over the specified pair of sequences in sync, /// up to the end of the shorter sequence. /// </summary> /// <param name="sequence1">The first sequence over which to iterate.</param> /// <param name="sequence2">The second sequence over which to iterate.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="sequence1"/> or <paramref name="sequence2"/> is <see langword="null"/>. /// </exception> public EnumeratorPair(IEnumerable <T> sequence1, IEnumerable <T> sequence2) { ArgumentValidate.NotNull(sequence1, nameof(sequence1)); ArgumentValidate.NotNull(sequence2, nameof(sequence2)); _enumerator1 = sequence1.GetEnumerator(); _enumerator2 = sequence2.GetEnumerator(); }
/// <summary> /// Gets the User-Agent header of the client from which the incoming message was sent. /// </summary> /// <param name="context">The execution context for the current WCF service method.</param> /// <returns>The User-Agent header of the client.</returns> public static string GetUserAgent(this OperationContext context) { ArgumentValidate.NotNull(context, nameof(context)); var httpRequest = context.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; return(httpRequest.Headers[HttpRequestHeader.UserAgent]); }
/// <summary> /// Gets the IP address of the client from which the incoming message was sent. /// </summary> /// <param name="context">The execution context for the current WCF service method.</param> /// <returns>The IP address of the client.</returns> /// <remarks> /// <list type="bullet"> /// <listheader>References</listheader> /// <item><see href="http://stackoverflow.com/a/93437/1149773">Obtaining client IP address in WCF</see>, <i>Stack Overflow</i></item> /// </list> /// </remarks> public static string GetUserHostAddress(this OperationContext context) { ArgumentValidate.NotNull(context, nameof(context)); var remoteEndpoint = context.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; return(remoteEndpoint.Address); }
/// <summary> /// Returns a value indicating whether the specified substring occurs within the source string, /// using the specified string comparison for the search. /// </summary> /// <param name="source">The source string in which to search.</param> /// <param name="value">The string to seek.</param> /// <param name="comparisonType">One of the enumeration values that specifies the rules for the search.</param> /// <returns> /// <see langword="true"/> if the <paramref name="value"/> parameter occurs within the <paramref name="source"/> string, /// or if <paramref name="value"/> is the empty string (<c>""</c>); /// otherwise, <see langword="false"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="value"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentException"><paramref name="comparisonType"/> is not a valid <see cref="StringComparison"/> value.</exception> /// <remarks> /// The built-in <see cref="string.Contains(string)"/> method performs an ordinal (case-sensitive and culture-insensitive) comparison. /// This extension method allows the comparison type to be specified. /// </remarks> public static bool Contains(this string source, string value, StringComparison comparisonType) { ArgumentValidate.NotNull(source, nameof(source)); ArgumentValidate.NotNull(value, nameof(value)); ArgumentValidate.EnumDefined(comparisonType, nameof(comparisonType)); return(source.IndexOf(value, comparisonType) >= 0); }
/// <summary> /// Reports the zero-based index and length of the first occurrence of the specified substring in the source string. /// </summary> /// <param name="source">The source string in which to search.</param> /// <param name="substring">The substring to seek.</param> /// <param name="comparisonType">One of the enumeration values that specifies the rules for the search.</param> /// <param name="matchIndex"> /// When this method returns, contains the zero-based starting character position of the match, if found; /// or -1 if no match is found. /// If <paramref name="substring"/> is the empty string (<c>""</c>), the value will be 0. /// </param> /// <param name="matchLength"> /// When this method returns, contains the length (in characters) of the match, if found; /// or -1 if no match is found. /// If <paramref name="substring"/> is the empty string (<c>""</c>), the value will be 0. /// </param> /// <remarks> /// Refer to the remarks on the <see cref="Find(string, string, int, int, StringComparison, out int, out int)"/> overload. /// </remarks> public static void Find(this string source, string substring, StringComparison comparisonType, out int matchIndex, out int matchLength) { ArgumentValidate.NotNull(source, nameof(source)); ArgumentValidate.NotNull(substring, nameof(substring)); ArgumentValidate.EnumDefined(comparisonType, nameof(comparisonType)); FindInner(source, substring, 0, source.Length, comparisonType, out matchIndex, out matchLength); }
/// <summary> /// Reports the zero-based index and length of the first occurrence of the specified substring in the source string. /// </summary> /// <param name="source">The source string in which to search.</param> /// <param name="searchValue">The substring to seek.</param> /// <param name="comparisonType">One of the enumeration values that specifies the rules for the search.</param> /// <param name="matchIndex"> /// When this method returns, contains the zero-based starting character position of the match, if found; /// or -1 if no match is found. /// If <paramref name="searchValue"/> is the empty string (<c>""</c>), the value will be 0. /// </param> /// <param name="matchLength"> /// When this method returns, contains the length (in characters) of the match, if found; /// or -1 if no match is found. /// If <paramref name="searchValue"/> is the empty string (<c>""</c>), the value will be 0. /// </param> /// <returns> /// <see langword="true"/> if a match for <paramref name="searchValue"/> is found in the source string; /// otherwise, <see langword="false"/>. /// </returns> /// <remarks> /// Refer to the remarks on the /// <see cref="Find(string, string, int, int, StringComparison, out int, out int)"/> overload. /// </remarks> public static bool Find(this string source, string searchValue, StringComparison comparisonType, out int matchIndex, out int matchLength) { ArgumentValidate.NotNull(source, nameof(source)); ArgumentValidate.NotNull(searchValue, nameof(searchValue)); ArgumentValidate.EnumDefined(comparisonType, nameof(comparisonType)); return(FindInner(source, searchValue, 0, source.Length, comparisonType, out matchIndex, out matchLength)); }
/// <summary> /// Creates or overwrites a file in the specified path. /// </summary> /// <param name="path">The path and name of the empty file to create.</param> /// <remarks> /// <list type="bullet"> /// <listheader>References</listheader> /// <item><see href="http://stackoverflow.com/q/802541/1149773">Creating an empty file in C#</see>, <i>Stack Overflow</i></item> /// </list> /// </remarks> public static void CreateEmpty(string path) { ArgumentValidate.NotNull(path, nameof(path)); using (File.Create(path)) { // Do nothing; just need "using" statement to dispose the file stream. } }
/// <summary> /// Verifies that the specified sequence is empty. /// The assertion fails if the sequence contains any elements. /// </summary> /// <typeparam name="T">The type of the elements of <paramref name="sequence"/>.</typeparam> /// <param name="sequence">The sequence that should be empty.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> public static void IsEmpty <T>(IEnumerable <T> sequence, string message = "") { ArgumentValidate.NotNull(sequence, nameof(sequence)); if (sequence.Any()) { throw new AssertFailedException($"The sequence was expected to be empty, but actually contains {sequence.Count()} element(s). {message}"); } }
/// <summary> /// Verifies that an exception (of any type) is thrown during the asynchronous execution of <paramref name="asyncFunc"/>. /// The assertion fails if no uncaught exception is thrown. /// </summary> /// <param name="asyncFunc">The asynchronous delegate that should throw the exception.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> /// <returns> /// A task that represents the asynchronous operation. /// The task result contains the exception that was thrown by <paramref name="asyncFunc"/>. /// </returns> /// <remarks> /// Refer to the remarks on the <see cref="ThrowsAsync{TException}(Func{Task}, string)"/> overload. /// </remarks> public static Task <Exception> ThrowsAsync(Func <Task> asyncFunc, string message = null) { ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); return(ThrowsAsyncInner <Exception>(asyncFunc, $"Expected exception, but none was thrown. {message}", t => $"Expected exception, but \"{t.Name}\" was thrown instead. {message}")); // Message for wrong type should never actually be needed. }
/// <summary> /// Verifies that an exception (of any type) is thrown during the execution of <paramref name="action"/>. /// The assertion fails if no uncaught exception is thrown. /// </summary> /// <param name="action">The action delegate that should throw the exception.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> /// <returns>The exception that was thrown by <paramref name="action"/>.</returns> /// <remarks> /// Refer to the remarks on the <see cref="Throws{TException}(Action, string)"/> overload. /// </remarks> public static Exception Throws(Action action, string message = null) { ArgumentValidate.NotNull(action, nameof(action)); var asyncFunc = action.WrapAsync(); var task = ThrowsAsync(asyncFunc, message); return(task.GetResult()); // task is always completed; returns immediately }
/// <summary> /// Executes the specified asynchronous function delegate using the disposable resource, /// then disposes of the said resource by calling its <see cref="IDisposable.Dispose()"/> method. /// </summary> /// <typeparam name="TDisposable">The type of the disposable resource to use.</typeparam> /// <typeparam name="TResult">The type of the return value of the asynchronous function delegate.</typeparam> /// <param name="disposable">The disposable resource to use.</param> /// <param name="strategy"> /// The strategy for propagating or swallowing exceptions thrown by the <see cref="IDisposable.Dispose"/> method. /// </param> /// <param name="asyncFunc">The asynchronous function delegate to execute using the disposable resource.</param> /// <returns> /// A task that represents the asynchronous operation. /// The task result contains the return value of the asynchronous function delegate. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="disposable"/> or <paramref name="asyncFunc"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="Using{TDisposable}(TDisposable, DisposeExceptionStrategy, Action{TDisposable})"/> overload. /// </remarks> public static Task <TResult> UsingAsync <TDisposable, TResult>(this TDisposable disposable, DisposeExceptionStrategy strategy, Func <TDisposable, Task <TResult> > asyncFunc) where TDisposable : IDisposable { ArgumentValidate.NotNull(disposable, nameof(disposable)); ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); ArgumentValidate.EnumDefined(strategy, nameof(strategy)); return(disposable.UsingAsyncInner(strategy, asyncFunc)); }
/// <summary> /// Creates and starts a new thread to execute the specified action delegate. /// </summary> /// <param name="action">The action delegate to execute in the thread.</param> /// <returns>The created thread.</returns> /// <remarks> /// <para> /// This method initializes a new thread through the <see cref="Thread(ThreadStart)"/> /// constructor and calls its <see cref="Thread.Start()"/> method. /// Its purpose is conceptually similar /// to the <see cref="TaskFactory.StartNew(Action)"/> method of the <see cref="TaskFactory"/> class, /// or the <see cref="Task.Run(Action)"/> method of the <see cref="Task"/> class, /// but operates at the level of threads rather than tasks. /// </para> /// <para> /// Be careful with captured variables in the closure of the <paramref name="action"/> delegate. /// In the example below, the loop counter <c>i</c> is captured by the lambda expression; /// its value is likely to have been incremented <i>before</i> being read by the new thread. /// Consequently, the same value might be output by multiple threads; in the worst case, /// all threads would output the final value "8". /// <code> /// var threads = new Thread[8]; /// for (int i = 0; i < threads.Length; i++) /// threads[i] = ThreadUtility.StartNew(() => Console.WriteLine(i)); /// for (int i = 0; i < threads.Length; i++) /// threads[i].Join(); /// </code> /// This issue can be fixed by using the <see cref="StartNew{TParam}(TParam, Action{TParam})"/> /// parameterized overload instead, passing the loop counter as the parameter: /// <code> /// var threads = new Thread[8]; /// for (int i = 0; i < threads.Length; i++) /// threads[i] = ThreadUtility.StartNew(i, x => Console.WriteLine(x)); /// for (int i = 0; i < threads.Length; i++) /// threads[i].Join(); /// </code> /// Alternatively, one could use LINQ and avoid the need of a loop counter altogether: /// <code> /// Enumerable.Range(0, 8) /// .Select(i => ThreadUtility.StartNew(() => Console.WriteLine(i))) /// .ToList() /// .ForEach(thread => thread.Join()); /// </code> /// </para> /// </remarks> public static Thread StartNew(Action action) { ArgumentValidate.NotNull(action, nameof(action)); var thread = new Thread(new ThreadStart(action)); thread.Start(); return(thread); }
/// <summary> /// Returns an array of bytes filled with random numbers. /// </summary> /// <param name="random">The <see cref="Random"/> instance to generate the random numbers.</param> /// <param name="length">The length of the array of bytes to fill.</param> /// <returns>The array of bytes containing random numbers.</returns> /// <exception cref="ArgumentNullException"><paramref name="random"/> is <see langword="null"/>.</exception> public static byte[] NextBytes(this Random random, int length) { ArgumentValidate.NotNull(random, nameof(random)); var buffer = new byte[length]; random.NextBytes(buffer); return(buffer); }
/// <summary> /// Verifies that an exception of type <typeparamref name="TException"/> (or derived therefrom) /// is thrown during the asynchronous execution of <paramref name="asyncAction"/>. /// The assertion fails if no uncaught exception is thrown, /// of if another type of exception is thrown. /// </summary> /// <typeparam name="TException">The type of the exception expected to be thrown.</typeparam> /// <param name="asyncAction">The asynchronous delegate that should throw the exception.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> /// <returns> /// A task that represents the asynchronous operation. /// The task result contains the exception that was thrown by <paramref name="asyncAction"/>. /// </returns> /// <remarks> /// <para> /// This method extends the <see cref="Throws{TException}(Action, string)"/> overload to support asynchronous delegates. /// Refer to the remarks on the said overload for the general functionality of these methods. /// </para> /// <list type="bullet"> /// <listheader>References</listheader> /// <item><see href="https://msdn.microsoft.com/en-us/magazine/dn818493.aspx#code-snippet-8">Async Programming : Unit Testing Asynchronous Code</see> by Stephen Cleary</item> /// </list> /// </remarks> /// <example> /// <code> /// var exception = await ExceptionAssert.ThrowsAsync<ArgumentNullException>(async () => /// { /// using (var stream = new MemoryStream()) /// { /// var buffer = new byte[128]; /// await stream.ReadAsync(buffer, 0, 256).ConfigureAwait(false); /// } /// }); /// </code> /// </example> public static Task <TException> ThrowsAsync <TException>(Func <Task> asyncAction, string message = null) where TException : Exception { ArgumentValidate.NotNull(asyncAction, nameof(asyncAction)); return(ThrowsAsyncInner <TException>(asyncAction, $"Expected exception of type \"{typeof(TException).Name}\", but no exception was thrown. {message}", t => $"Expected exception of type \"{typeof(TException).Name}\", but \"{t.Name}\" was thrown instead. {message}")); }
/// <summary> /// Creates a sequence consisting of the specified elements. /// </summary> /// <typeparam name="TSource">The type of the elements of the sequence.</typeparam> /// <param name="elements">The elements from which to create the sequence.</param> /// <returns>A sequence that contains the items in <paramref name="elements"/>.</returns> /// <remarks> /// <see href="http://stackoverflow.com/a/1577868/1149773">Jon Skeet recommends</see> against returning a list or an array, /// since an unscrupulous consumer could cast it back and change its contents, breaking the expected immutable behavior /// for other consumers of the same sequence. /// </remarks> public static IEnumerable <TSource> Yield <TSource>(params TSource[] elements) { ArgumentValidate.NotNull(elements, nameof(elements)); foreach (var element in elements) { yield return(element); } }
/// <summary> /// Verifies that the specified sequence contains the specified number of elements. /// </summary> /// <typeparam name="T">The type of the elements of <paramref name="sequence"/>.</typeparam> /// <param name="count">The expected number of elements that the sequence should contain.</param> /// <param name="sequence">The sequence that should <paramref name="count"/> elements.</param> /// <param name="message">A message to display if the assertion fails. This message can be seen in the unit test results.</param> public static void HasCount <T>(int count, IEnumerable <T> sequence, string message = "") { ArgumentValidate.NotNull(sequence, nameof(sequence)); if (sequence.Count() != count) { throw new AssertFailedException($"The sequence was expected to contain {count} element(s), but actually contains {sequence.Count()}. {message}"); } }
/// <summary> /// Transforms the asynchronous function delegate to deliver all exceptions asynchronously, /// through the returned <see cref="Task{TResult}"/>. /// This includes exceptions thrown from the synchronous part of the original asynchronous delegate, /// which would otherwise be thrown directly to the caller as soon as the delegate is invoked. /// </summary> /// <typeparam name="T">The type of the parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="asyncFunc">The asynchronous function delegate to be transformed.</param> /// <returns>The asynchronous function delegate encapsulating <paramref name="asyncFunc"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="asyncFunc"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="AsyncActionExtensions.DeliverAsync(Func{Task})"/> extension method. /// </remarks> public static Func <T, Task <TResult> > DeliverAsync <T, TResult>(this Func <T, Task <TResult> > asyncFunc) { ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); return(async(T arg) => { return await asyncFunc(arg).ConfigureAwait(false); }); }
/// <summary> /// Creates an asynchronous delegate that executes the specified function delegate synchronously /// and returns a task that has completed successfully with the said delegate's result /// (like through <see cref="Task.FromResult{TResult}(TResult)"/>). /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the delegate.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the delegate.</typeparam> /// <typeparam name="T6">The type of the sixth parameter of the delegate.</typeparam> /// <typeparam name="T7">The type of the seventh parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="func">The function delegate to be executed synchronously by the asynchronous delegate.</param> /// <returns>The asynchronous delegate encapsulating <paramref name="func"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="func"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="WrapAsync{TResult}(Func{TResult})"/> overload. /// </remarks> public static Func <T1, T2, T3, T4, T5, T6, T7, Task <TResult> > WrapAsync <T1, T2, T3, T4, T5, T6, T7, TResult>(this Func <T1, T2, T3, T4, T5, T6, T7, TResult> func) { ArgumentValidate.NotNull(func, nameof(func)); return((T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) => { var result = func(arg1, arg2, arg3, arg4, arg5, arg6, arg7); return Task.FromResult(result); }); }
/// <summary> /// Creates and starts a new thread to execute the specified action delegate, /// supplying the specified parameter value. /// </summary> /// <typeparam name="TParam">The type of the parameter to be supplied to the action delegate.</typeparam> /// <param name="parameter">The parameter to be supplied to the action delegate.</param> /// <param name="action"> /// The action delegate to execute in the thread. /// When run, the delegate will be passed <paramref name="parameter"/> as an argument. /// </param> /// <returns>The created thread.</returns> /// <remarks> /// <para> /// This method initializes a new thread through the <see cref="Thread(ParameterizedThreadStart)"/> /// constructor and calls its <see cref="Thread.Start(object)"/> method, /// supplying <paramref name="parameter"/> as the argument. /// Its purpose is conceptually similar to the <see cref="TaskFactory.StartNew(Action{object}, object)"/> method /// of the <see cref="TaskFactory"/> class, but operates at the level of threads rather than tasks. /// Unlike the .NET Framework classes, this method uses generics to ensure compile-time type safety. /// </para> /// <para> /// Refer to the remarks on the <see cref="StartNew(Action)"/> overload regarding captured variables. /// </para> /// </remarks> public static Thread StartNew <TParam>(TParam parameter, Action <TParam> action) { ArgumentValidate.NotNull(action, nameof(action)); Action <object> actionObj = (object obj) => action((TParam)obj); var thread = new Thread(new ParameterizedThreadStart(actionObj)); thread.Start(parameter); return(thread); }
/// <summary> /// Creates an asynchronous delegate that executes the specified function delegate synchronously /// and returns a task that has completed successfully with the said delegate's result /// (like through <see cref="Task.FromResult{TResult}(TResult)"/>). /// </summary> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="func">The function delegate to be executed synchronously by the asynchronous delegate.</param> /// <returns>The asynchronous delegate encapsulating <paramref name="func"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="func"/> is <see langword="null"/>.</exception> /// <remarks> /// <para> /// This method does not immediately execute the <paramref name="func"/> delegate. /// Rather, <paramref name="func"/> is encapsulated within an asynchronous delegate, /// and will be executed when the latter is invoked. /// In the case of an unhandled exception thrown by <paramref name="func"/>, /// the exception is propagated to the caller of the asynchronous delegate. /// </para> /// <para> /// The asynchronous delegate created by this method is just a <see cref="Task{TResult}"/>-returning wrapper over the /// <paramref name="func"/> delegate. It <i>does not</i> queue the specified work to run on the thread pool. /// For such functionality, use the <see cref="Task.Run{TResult}(Func{TResult})"/> method of the <see cref="Task"/> class. /// </para> /// <para> /// The asynchronous delegate created by this method delivers exceptions synchronously. /// This means that, if <paramref name="func"/> throws an unhandled exception, it will be propagated directly to its caller, /// and not encapsulated in the returned <see cref="Task{TResult}"/> (making it <see cref="TaskStatus.Faulted"/>). /// To get exceptions delivered asynchronously through the returned <see cref="Task{TResult}"/>, use the /// <see cref="AsyncFuncExtensions.DeliverAsync{TResult}(Func{Task{TResult}})"/> extension method on the created delegate. /// </para> /// <para> /// This method is convenient when implementing a pair of method overloads for some delegate-based functionality, /// with one overload taking an <see cref="Func{TResult}"/> parameter, and the other an asynchronous /// <see cref="Func{T}"/> of <see cref="Task{TResult}"/>, /// such as is the case for <see cref="Task.Run{TResult}(Func{TResult})"/> and <see cref="Task.Run{TResult}(Func{Task{TResult}})"/>. /// The function overload can be implemented by calling this <see cref="WrapAsync{TResult}(Func{TResult})"/> method /// on the <see cref="Func{TResult}"/> argument to convert it to an asynchronous <see cref="Func{T}"/> of <see cref="Task{TResult}"/> /// delegate returning a completed task with the former delegate's result, and then passing the created delegate /// to the asynchronous overload. /// </para> /// </remarks> /// <example> /// <code> /// public static TResult DoSomething<TResult>(Func<TResult> func) /// { /// ArgumentValidate.NotNull(func, nameof(func)); /// /// var asyncFunc = func.WrapAsync(); /// var task = DoSomething(asyncFunc); /// return task.GetAwaiter().GetResult(); // task is always completed; returns immediately /// } /// /// public static async Task<TResult> DoSomething<TResult>(Func<Task<TResult>> asyncFunc) /// { /// ArgumentValidate.NotNull(asyncFunc, nameof(asyncFunc)); /// /// // preprocessing /// /// try /// { /// return await asyncFunc().ConfigureAwait(false); /// } /// finally /// { /// // postprocessing /// } /// } /// </code> /// </example> public static Func <Task <TResult> > WrapAsync <TResult>(this Func <TResult> func) { ArgumentValidate.NotNull(func, nameof(func)); return(() => { var result = func(); return Task.FromResult(result); }); }
/// <summary> /// Creates an asynchronous delegate that executes the specified function delegate synchronously /// and returns a task that has completed successfully with the said delegate's result /// (like through <see cref="Task.FromResult{TResult}(TResult)"/>). /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the delegate.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the delegate.</typeparam> /// <typeparam name="T6">The type of the sixth parameter of the delegate.</typeparam> /// <typeparam name="T7">The type of the seventh parameter of the delegate.</typeparam> /// <typeparam name="T8">The type of the eighth parameter of the delegate.</typeparam> /// <typeparam name="T9">The type of the ninth parameter of the delegate.</typeparam> /// <typeparam name="T10">The type of the tenth parameter of the delegate.</typeparam> /// <typeparam name="T11">The type of the eleventh parameter of the delegate.</typeparam> /// <typeparam name="T12">The type of the twelfth parameter of the delegate.</typeparam> /// <typeparam name="T13">The type of the thirteenth parameter of the delegate.</typeparam> /// <typeparam name="T14">The type of the fourteenth parameter of the delegate.</typeparam> /// <typeparam name="T15">The type of the fifteenth parameter of the delegate.</typeparam> /// <typeparam name="T16">The type of the sixteenth parameter of the delegate.</typeparam> /// <typeparam name="TResult">The type of the return value of the delegate.</typeparam> /// <param name="func">The function delegate to be executed synchronously by the asynchronous delegate.</param> /// <returns>The asynchronous delegate encapsulating <paramref name="func"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="func"/> is <see langword="null"/>.</exception> /// <remarks> /// Refer to the remarks on the <see cref="WrapAsync{TResult}(Func{TResult})"/> overload. /// </remarks> public static Func <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, Task <TResult> > WrapAsync <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(this Func <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> func) { ArgumentValidate.NotNull(func, nameof(func)); return((T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) => { var result = func(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); return Task.FromResult(result); }); }