Skip to content

Commit

Permalink
Move namespace Leaf.Core.Extensions.System to Leaf.Core.Extensions.
Browse files Browse the repository at this point in the history
New methods: ThreadSafeUI.IsCanceledByUser(Exception).
New extensions:
SmtpClient.SendMailAsync(MailMessage, CancellationToken);
string.IsNullOrEmpty();
string.HasContent();
Task.Caf() = Task.ConfigureAwait(false);
  • Loading branch information
grandsilence committed Jan 24, 2019
1 parent 15081b9 commit e8af6d3
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Leaf.Core.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=_041F_043E_0442_043E_043A_043E_0431_0435_0437_043E_043F_0430_0441_043D_0430_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_041F_043E_0442_043E_043A_043E_0431_0435_0437_043E_043F_0430_0441_043D_043E_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0422_043E_043A_0435_043D/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_042D_043A_0437_0435_043C_043B_044F_0440/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043B_043E_0433_0438_043D_043E_0432/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043C_043D_043E_0433_043E_043F_043E_0442_043E_0447_043D_043E_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043C_043D_043E_0433_043E_043F_043E_0442_043E_0447_043D_0443_044E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043E_043F_0446_0438_043E_043D_0430_043B_044C_043D_0430_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_0430_0442_0442_0435_0440_043D/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_043E_043F_0430_043F_0430_044E_0442/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_043E_0442_043E_043A_043E_0431_0435_0437_043E_043F_0430_0441_043D_043E_0433_043E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_043E_0442_043E_043A_043E_0431_0435_0437_043E_043F_0430_0441_043D_043E_0439/@EntryIndexedValue">True</s:Boolean>
Expand Down
1 change: 1 addition & 0 deletions Leaf.Core.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNamingAutoDetectionCompleted/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="Between" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=EnumMember/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Globalization;

namespace Leaf.Core.Extensions.System
namespace Leaf.Core.Extensions
{
public static class DateTimeExtensions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Text;

namespace Leaf.Core.Extensions.System
namespace Leaf.Core.Extensions
{
/// <summary>
/// Делегат, обрабатывающий исключение внутри нескольких исключений (объединённых).
Expand Down
77 changes: 77 additions & 0 deletions Leaf.Core/Extensions/Net/SmtpClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Sends the specified message to an SMTP server for delivery as an asynchronous operation.
/// </summary>
/// <param name="client">
/// The <see cref="SmtpClient"/> instance.
/// </param>
/// <param name="message">The <see cref="MailMessage"/> to send.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="client"/> is <see langword="null"/>.</para>
/// <para>-or-</para>
/// <para><paramref name="message"/> is <see langword="null"/>.</para>
/// </exception>
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<object>();
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;
}

}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Globalization;
using Leaf.Core.Extensions.String;

namespace Leaf.Core.Extensions.System
namespace Leaf.Core.Extensions
{
/// <summary>
/// Расширения для форматирования чисел к виду с разделителем тысяч.
Expand Down
14 changes: 14 additions & 0 deletions Leaf.Core/Extensions/String/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ public static bool IsWebLink(this string self, bool trim = false)
/// <returns>Вернет <see langword="null"/> если строка равна <see cref="string.Empty"/>.</returns>
public static string NullOnEmpty(this string self) => self == string.Empty ? null : self;

/// <inheritdoc cref="string.IsNullOrEmpty"/>
/// <summary>
/// Расширение для метода <see cref="string.IsNullOrEmpty"/>.
/// </summary>
/// <param name="self">Строка</param>
public static bool IsNullOrEmpty(this string self) => string.IsNullOrEmpty(self);

/// <summary>
/// Проверка строки на полезный контент.
/// </summary>
/// <param name="self">Строка</param>
/// <returns>Вернет <see langword="true" /> если строка не является <see langword="null"/>, пустой строкой и пробелами.</returns>
public static bool HasContent(this string self) => !string.IsNullOrWhiteSpace(self);

/// <summary>
/// Проверяет наличие слова в строке, аналогично <see cref="string.Contains(string)"/>, но без учета реестра и региональных стандартов.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions Leaf.Core/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -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<T> Caf<T>(this Task<T> task) => task.ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Globalization;
using System.Text;

namespace Leaf.Core.Extensions.System
namespace Leaf.Core.Extensions
{
/// <summary>
/// Расширения при работе со временем.
Expand Down
7 changes: 7 additions & 0 deletions Leaf.Core/Threading/ThreadSafeUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ public abstract class ThreadSafeUI
/// </summary>
public bool IsCanceled => CancelToken.IsCancellationRequested;

/// <summary>
/// Возвращает истину если исключение является <see cref="OperationCanceledException"/> и <see cref="CancelToken"/> был отменен.
/// </summary>
/// <param name="ex">Исключение которое было брошено</param>
/// <returns>Вернет истину если работа была отменена пользователем через <see cref="CancelToken"/>.</returns>
public bool IsCanceledByUser(Exception ex) => ex is OperationCanceledException && IsCanceled;

/// <summary>
/// Создает потокобезопасную реализацию для работы с интерфейсом.
/// </summary>
Expand Down

0 comments on commit e8af6d3

Please sign in to comment.