You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
7.9 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Runtime.InteropServices;
  7. using System.Security.Permissions;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace Net3_Proxy
  12. {
  13. public static class Extensions
  14. {
  15. public static T GetCustomAttribute<T>(this ParameterInfo element) where T : Attribute
  16. => (T)GetCustomAttribute(element, typeof(T));
  17. public static T GetCustomAttribute<T>(this MethodInfo element) where T : Attribute
  18. => (T)GetCustomAttribute(element, typeof(T));
  19. public static T GetCustomAttribute<T>(this ConstructorInfo element) where T : Attribute
  20. => (T)GetCustomAttribute(element, typeof(T));
  21. public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType)
  22. => Attribute.GetCustomAttribute(element, attributeType);
  23. public static Attribute GetCustomAttribute(this ConstructorInfo element, Type attributeType)
  24. => Attribute.GetCustomAttribute(element, attributeType);
  25. public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType)
  26. => Attribute.GetCustomAttribute(element, attributeType);
  27. public static StringBuilder Clear(this StringBuilder sb)
  28. => sb.Remove(0, sb.Length);
  29. public static bool HasFlag<E>(this E e, E o) where E : Enum
  30. {
  31. var ei = Convert.ToUInt64(e);
  32. var oi = Convert.ToUInt64(o);
  33. return (ei & oi) == oi;
  34. }
  35. }
  36. public static class DirectoryInfoExtensions
  37. {
  38. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self)
  39. {
  40. return self.EnumerateFiles("*", SearchOption.TopDirectoryOnly);
  41. }
  42. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern)
  43. {
  44. return self.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
  45. }
  46. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern, SearchOption searchOption)
  47. {
  48. if (searchPattern == null)
  49. {
  50. throw new ArgumentNullException(nameof(searchPattern));
  51. }
  52. return CreateEnumerateFilesIterator(self, searchPattern, searchOption);
  53. }
  54. private static IEnumerable<FileInfo> CreateEnumerateFilesIterator(DirectoryInfo self, string searchPattern, SearchOption searchOption)
  55. {
  56. foreach (string fileName in Directory.GetFiles(self.FullName, searchPattern, searchOption))
  57. yield return new FileInfo(fileName);
  58. yield break;
  59. }
  60. }
  61. public static class StreamExtensions
  62. {
  63. [ComVisible(false)]
  64. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  65. public static Task CopyToAsync(this Stream src, Stream destination) => CopyToAsync(src, destination, 81920);
  66. [ComVisible(false)]
  67. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  68. public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize) => CopyToAsync(src, destination, bufferSize, CancellationToken.None);
  69. [ComVisible(false)]
  70. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  71. public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
  72. {
  73. if (destination == null)
  74. {
  75. throw new ArgumentNullException(nameof(destination));
  76. }
  77. if (bufferSize <= 0)
  78. {
  79. throw new ArgumentOutOfRangeException(nameof(bufferSize), "Positive number required.");
  80. }
  81. if (!src.CanRead && !src.CanWrite)
  82. {
  83. throw new ObjectDisposedException(null, "Cannot access a closed Stream.");
  84. }
  85. if (!destination.CanRead && !destination.CanWrite)
  86. {
  87. throw new ObjectDisposedException("destination", "Cannot access a closed Stream.");
  88. }
  89. if (!src.CanRead)
  90. {
  91. throw new NotSupportedException("Stream does not support reading.");
  92. }
  93. if (!destination.CanWrite)
  94. {
  95. throw new NotSupportedException("Stream does not support writing.");
  96. }
  97. return CopyToAsyncInternal(src, destination, bufferSize, cancellationToken);
  98. }
  99. private static async Task CopyToAsyncInternal(Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
  100. {
  101. byte[] buffer = new byte[bufferSize];
  102. int bytesRead;
  103. while ((bytesRead = await src.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) != 0)
  104. {
  105. await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
  106. }
  107. }
  108. [ComVisible(false)]
  109. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  110. public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count)
  111. {
  112. return ReadAsync(src, buffer, offset, count, CancellationToken.None);
  113. }
  114. [ComVisible(false)]
  115. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  116. public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  117. {
  118. if (!cancellationToken.IsCancellationRequested)
  119. {
  120. return BeginEndReadAsync(src, buffer, offset, count);
  121. }
  122. return new Task<int>(() => 0, cancellationToken);
  123. }
  124. private static Task<int> BeginEndReadAsync(Stream src, byte[] buffer, int offset, int count)
  125. => Task<int>.Factory.FromAsync(
  126. (byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
  127. src.BeginRead(buffer_, offset_, count_, callback, state),
  128. (IAsyncResult asyncResult) => src.EndRead(asyncResult),
  129. buffer,
  130. offset,
  131. count,
  132. new object());
  133. [ComVisible(false)]
  134. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  135. public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count)
  136. {
  137. return WriteAsync(src, buffer, offset, count, CancellationToken.None);
  138. }
  139. [ComVisible(false)]
  140. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  141. public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  142. {
  143. if (!cancellationToken.IsCancellationRequested)
  144. {
  145. return BeginEndWriteAsync(src, buffer, offset, count);
  146. }
  147. return new Task<int>(() => 0, cancellationToken);
  148. }
  149. private static Task BeginEndWriteAsync(Stream src, byte[] buffer, int offset, int count)
  150. => Task.Factory.FromAsync(
  151. (byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
  152. src.BeginWrite(buffer_, offset_, count_, callback, state),
  153. (IAsyncResult asyncResult) => src.EndWrite(asyncResult),
  154. buffer,
  155. offset,
  156. count,
  157. new object());
  158. }
  159. public static class SemaphoreSlimExtesnions
  160. { // TODO: finish the WaitAsync members
  161. /*public static Task WaitAsync(this SemaphoreSlim self)
  162. {
  163. return null;
  164. }*/
  165. }
  166. }