From e8af6d34cc94aa909f4226e2df46cad1303ac034 Mon Sep 17 00:00:00 2001 From: Grand Silence Date: Thu, 24 Jan 2019 03:55:07 +0300 Subject: [PATCH] Move namespace Leaf.Core.Extensions.System to Leaf.Core.Extensions. New methods: ThreadSafeUI.IsCanceledByUser(Exception). New extensions: SmtpClient.SendMailAsync(MailMessage, CancellationToken); string.IsNullOrEmpty(); string.HasContent(); Task.Caf() = Task.ConfigureAwait(false); --- Leaf.Core.sln.DotSettings | 2 + Leaf.Core.sln.DotSettings.user | 1 + .../{System => }/DateTimeExtensions.cs | 2 +- .../{System => }/ExceptionExtensions.cs | 2 +- .../Extensions/Net/SmtpClientExtensions.cs | 77 +++++++++++++++++++ .../{System => }/NumberFormatExtensions.cs | 2 +- .../Extensions/String/StringExtensions.cs | 14 ++++ Leaf.Core/Extensions/TaskExtensions.cs | 11 +++ .../{System => }/TimeSpanExtensions.cs | 2 +- Leaf.Core/Threading/ThreadSafeUI.cs | 7 ++ 10 files changed, 116 insertions(+), 4 deletions(-) rename Leaf.Core/Extensions/{System => }/DateTimeExtensions.cs (95%) rename Leaf.Core/Extensions/{System => }/ExceptionExtensions.cs (99%) create mode 100644 Leaf.Core/Extensions/Net/SmtpClientExtensions.cs rename Leaf.Core/Extensions/{System => }/NumberFormatExtensions.cs (98%) create mode 100644 Leaf.Core/Extensions/TaskExtensions.cs rename Leaf.Core/Extensions/{System => }/TimeSpanExtensions.cs (96%) diff --git a/Leaf.Core.sln.DotSettings b/Leaf.Core.sln.DotSettings index 0ca0c0f..e2bef62 100644 --- a/Leaf.Core.sln.DotSettings +++ b/Leaf.Core.sln.DotSettings @@ -6,10 +6,12 @@ True True True + True True True True True + True True True True diff --git a/Leaf.Core.sln.DotSettings.user b/Leaf.Core.sln.DotSettings.user index ebe0e22..ab9cdd8 100644 --- a/Leaf.Core.sln.DotSettings.user +++ b/Leaf.Core.sln.DotSettings.user @@ -1,5 +1,6 @@  True + True True <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="Between" Suffix="" Style="AaBb" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> diff --git a/Leaf.Core/Extensions/System/DateTimeExtensions.cs b/Leaf.Core/Extensions/DateTimeExtensions.cs similarity index 95% rename from Leaf.Core/Extensions/System/DateTimeExtensions.cs rename to Leaf.Core/Extensions/DateTimeExtensions.cs index 3670dc6..07d4453 100644 --- a/Leaf.Core/Extensions/System/DateTimeExtensions.cs +++ b/Leaf.Core/Extensions/DateTimeExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Globalization; -namespace Leaf.Core.Extensions.System +namespace Leaf.Core.Extensions { public static class DateTimeExtensions { diff --git a/Leaf.Core/Extensions/System/ExceptionExtensions.cs b/Leaf.Core/Extensions/ExceptionExtensions.cs similarity index 99% rename from Leaf.Core/Extensions/System/ExceptionExtensions.cs rename to Leaf.Core/Extensions/ExceptionExtensions.cs index 422c45e..56db060 100644 --- a/Leaf.Core/Extensions/System/ExceptionExtensions.cs +++ b/Leaf.Core/Extensions/ExceptionExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Leaf.Core.Extensions.System +namespace Leaf.Core.Extensions { /// /// Делегат, обрабатывающий исключение внутри нескольких исключений (объединённых). diff --git a/Leaf.Core/Extensions/Net/SmtpClientExtensions.cs b/Leaf.Core/Extensions/Net/SmtpClientExtensions.cs new file mode 100644 index 0000000..694729f --- /dev/null +++ b/Leaf.Core/Extensions/Net/SmtpClientExtensions.cs @@ -0,0 +1,77 @@ +using System; +using System.Net.Mail; +using System.Threading; +using System.Threading.Tasks; + +namespace Leaf.Core.Extensions.Net +{ + public static class SmtpClientExtensions + { + /// + /// Sends the specified message to an SMTP server for delivery as an asynchronous operation. + /// + /// + /// The instance. + /// + /// The to send. + /// The to monitor for cancellation requests. + /// A representing the asynchronous operation. + /// + /// is . + /// -or- + /// is . + /// + public static Task SendMailAsync(this SmtpClient client, MailMessage message, CancellationToken cancellationToken) + { + if (client == null) throw new ArgumentNullException(nameof(client)); + if (message == null) throw new ArgumentNullException(nameof(message)); + if (!cancellationToken.CanBeCanceled) return client.SendMailAsync(message); + + var tcs = new TaskCompletionSource(); + var registration = default(CancellationTokenRegistration); + SendCompletedEventHandler handler = null; + + handler = (sender, e) => { + if (e.UserState != tcs) + return; + + try + { + if (handler == null) + return; + + client.SendCompleted -= handler; + handler = null; + } + finally + { + registration.Dispose(); + + if (e.Error != null) + tcs.TrySetException(e.Error); + else if (e.Cancelled) + tcs.TrySetCanceled(); + else + tcs.TrySetResult(null); + } + }; + + client.SendCompleted += handler; + + try + { + client.SendAsync(message, tcs); + registration = cancellationToken.Register(client.SendAsyncCancel); + } + catch + { + client.SendCompleted -= handler; + registration.Dispose(); + throw; + } + + return tcs.Task; + } + + } +} diff --git a/Leaf.Core/Extensions/System/NumberFormatExtensions.cs b/Leaf.Core/Extensions/NumberFormatExtensions.cs similarity index 98% rename from Leaf.Core/Extensions/System/NumberFormatExtensions.cs rename to Leaf.Core/Extensions/NumberFormatExtensions.cs index f35155d..9de07fd 100644 --- a/Leaf.Core/Extensions/System/NumberFormatExtensions.cs +++ b/Leaf.Core/Extensions/NumberFormatExtensions.cs @@ -1,7 +1,7 @@ using System.Globalization; using Leaf.Core.Extensions.String; -namespace Leaf.Core.Extensions.System +namespace Leaf.Core.Extensions { /// /// Расширения для форматирования чисел к виду с разделителем тысяч. diff --git a/Leaf.Core/Extensions/String/StringExtensions.cs b/Leaf.Core/Extensions/String/StringExtensions.cs index 4376ed2..39494e5 100644 --- a/Leaf.Core/Extensions/String/StringExtensions.cs +++ b/Leaf.Core/Extensions/String/StringExtensions.cs @@ -32,6 +32,20 @@ public static bool IsWebLink(this string self, bool trim = false) /// Вернет если строка равна . public static string NullOnEmpty(this string self) => self == string.Empty ? null : self; + /// + /// + /// Расширение для метода . + /// + /// Строка + public static bool IsNullOrEmpty(this string self) => string.IsNullOrEmpty(self); + + /// + /// Проверка строки на полезный контент. + /// + /// Строка + /// Вернет если строка не является , пустой строкой и пробелами. + public static bool HasContent(this string self) => !string.IsNullOrWhiteSpace(self); + /// /// Проверяет наличие слова в строке, аналогично , но без учета реестра и региональных стандартов. /// diff --git a/Leaf.Core/Extensions/TaskExtensions.cs b/Leaf.Core/Extensions/TaskExtensions.cs new file mode 100644 index 0000000..e27d1a2 --- /dev/null +++ b/Leaf.Core/Extensions/TaskExtensions.cs @@ -0,0 +1,11 @@ +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Leaf.Core.Extensions +{ + public static class TaskExtensions + { + public static ConfiguredTaskAwaitable Caf(this Task task) => task.ConfigureAwait(false); + public static ConfiguredTaskAwaitable Caf(this Task task) => task.ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/Leaf.Core/Extensions/System/TimeSpanExtensions.cs b/Leaf.Core/Extensions/TimeSpanExtensions.cs similarity index 96% rename from Leaf.Core/Extensions/System/TimeSpanExtensions.cs rename to Leaf.Core/Extensions/TimeSpanExtensions.cs index 768ccf0..3213d63 100644 --- a/Leaf.Core/Extensions/System/TimeSpanExtensions.cs +++ b/Leaf.Core/Extensions/TimeSpanExtensions.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Text; -namespace Leaf.Core.Extensions.System +namespace Leaf.Core.Extensions { /// /// Расширения при работе со временем. diff --git a/Leaf.Core/Threading/ThreadSafeUI.cs b/Leaf.Core/Threading/ThreadSafeUI.cs index f2e4ff4..8b6c0a9 100644 --- a/Leaf.Core/Threading/ThreadSafeUI.cs +++ b/Leaf.Core/Threading/ThreadSafeUI.cs @@ -65,6 +65,13 @@ public abstract class ThreadSafeUI /// public bool IsCanceled => CancelToken.IsCancellationRequested; + /// + /// Возвращает истину если исключение является и был отменен. + /// + /// Исключение которое было брошено + /// Вернет истину если работа была отменена пользователем через . + public bool IsCanceledByUser(Exception ex) => ex is OperationCanceledException && IsCanceled; + /// /// Создает потокобезопасную реализацию для работы с интерфейсом. ///