From 0b99ceb91036392fb84a67e53f42f15aa541c2b2 Mon Sep 17 00:00:00 2001 From: yangzheng06 Date: Fri, 8 Mar 2024 20:22:03 +0800 Subject: [PATCH] =?UTF-8?q?Added=20EnumDescriptionTypeConverter,update=20E?= =?UTF-8?q?numBindingSourceExtension=E3=80=81EnumExtensions=20and=20TaskEx?= =?UTF-8?q?tensions.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnumBindingSourceExtension.cs | 122 ++++++++++----- .../EnumDescriptionTypeConverter.cs | 59 +++++++ .../Extensions/EnumExtensions.cs | 25 +-- .../Extensions/TaskExtensions.cs | 146 ++++++++++-------- 4 files changed, 235 insertions(+), 117 deletions(-) create mode 100644 Source/Wif.Infrastructure/MarkupExtensions/EnumDescriptionTypeConverter.cs diff --git a/Source/Wif.Infrastructure/MarkupExtensions/EnumBindingSourceExtension.cs b/Source/Wif.Infrastructure/MarkupExtensions/EnumBindingSourceExtension.cs index 473ae7f..24075cb 100644 --- a/Source/Wif.Infrastructure/MarkupExtensions/EnumBindingSourceExtension.cs +++ b/Source/Wif.Infrastructure/MarkupExtensions/EnumBindingSourceExtension.cs @@ -9,90 +9,136 @@ using System; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Windows.Markup; namespace Frontier.Wif.Infrastructure.MarkupExtensions { /// - /// Markup extension for Enum values. - /// https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/ + /// 枚举值绑定源的标记扩展。参考 https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/ /// - public class EnumBindingSourceExtension - : MarkupExtension + public class EnumBindingSourceExtension : MarkupExtension { - #region Fields - /// - /// Defines the _enumType + /// 定义枚举类型字段。 /// private Type _enumType; - #endregion + /// + /// Initializes a new instance of the class. + /// + public EnumBindingSourceExtension() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// 枚举类型。 + public EnumBindingSourceExtension(Type enumType) + { + EnumType = enumType; + } - #region Properties + /// + /// Initializes a new instance of the class. + /// + /// 枚举类型。 + /// 枚举成员是否排序。 + public EnumBindingSourceExtension(Type enumType, bool isSorted) + { + EnumType = enumType; + IsSorted = isSorted; + } /// - /// Gets or sets the type of the Enum. + /// 获取或设置枚举类型。 /// public Type EnumType { - get => _enumType; + get { return _enumType; } set { if (value != EnumType) { if (!Equals(value, null) && !(Nullable.GetUnderlyingType(value) ?? value).IsEnum) + { throw new ArgumentException("Type must be an Enum."); + } _enumType = value; } } } - #endregion - - #region Constructors - /// - /// Initializes a new instance of the class. + /// 获取或设置是否排序,开启后获取EnumOrderAttribute值,若Attribute未设置,按照成员定义顺序排序。 /// - public EnumBindingSourceExtension() - { - } + public bool IsSorted { get; set; } /// - /// Initializes a new instance of the class. + /// 返回用作此标记扩展的目标属性值的对象。 /// - /// The type of the Enum. - public EnumBindingSourceExtension(Type enumType) - { - EnumType = enumType; - } - - #endregion - - #region Methods - - /// - /// The ProvideValue - /// - /// Object that can provide services for the markup extension. - /// The values of the Enum. + /// 为标记扩展提供服务的对象。 + /// 枚举的所有值。 public override object ProvideValue(IServiceProvider serviceProvider) { if (Equals(EnumType, null)) + { throw new InvalidOperationException("The type of the Enum is undefined."); + } + + Type underlyingEnumType = Nullable.GetUnderlyingType(EnumType) ?? EnumType; + + Array enumValues; + if (IsSorted) + { + enumValues = underlyingEnumType.GetFields().Where(field => field.IsStatic).Select(field => new + { + field, + attribute = field.GetCustomAttribute() + }).Select(fieldInfo => new + { + value = fieldInfo.field.GetValue(fieldInfo), + order = fieldInfo.attribute?.Order ?? 0 + }).OrderBy(field => field.order).Select(field => field.value).ToArray(); + } + else + { + enumValues = Enum.GetValues(underlyingEnumType); + } - var underlyingEnumType = Nullable.GetUnderlyingType(EnumType) ?? EnumType; - var enumValues = Enum.GetValues(underlyingEnumType); if (underlyingEnumType == EnumType) + { return enumValues; + } var nullableEnumValues = Array.CreateInstance(underlyingEnumType, enumValues.Length); enumValues.CopyTo(nullableEnumValues, 1); return nullableEnumValues; } + } - #endregion + /// + /// 表示在EnumBindingExtension中定义枚举成员顺序的特性。 + /// + [AttributeUsage(AttributeTargets.All, Inherited = false)] + public sealed class EnumOrderAttribute : Attribute + { + /// + /// 有参构造函数。 + /// + /// 枚举成员序号。 + public EnumOrderAttribute([CallerLineNumber] int order = 0) + { + Order = order; + } + + /// + /// 获取枚举成员序号。 + /// + public int Order { get; } } } \ No newline at end of file diff --git a/Source/Wif.Infrastructure/MarkupExtensions/EnumDescriptionTypeConverter.cs b/Source/Wif.Infrastructure/MarkupExtensions/EnumDescriptionTypeConverter.cs new file mode 100644 index 0000000..dd03541 --- /dev/null +++ b/Source/Wif.Infrastructure/MarkupExtensions/EnumDescriptionTypeConverter.cs @@ -0,0 +1,59 @@ +/************************************************************************** +* File Name:EnumBindingSourceExtension.cs +* Description:EnumBindingSourceExtension.cs class description... +* Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved. +* Creator:Leo Yang +* Create Time:2024/03/08 +*Project Address:https://github.com/LeoYang-Chuese/wif +**************************************************************************/ + + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; + +namespace Frontier.Wif.Infrastructure.MarkupExtensions +{ + /// + /// 表示枚举值转描述值的类型转换器。 + /// + public class EnumDescriptionTypeConverter : EnumConverter + { + /// + /// + /// + /// + public EnumDescriptionTypeConverter(Type type) : base(type) + { + } + + /// + /// + /// + /// + /// + /// + /// + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string)) + { + if (value != null) + { + FieldInfo fi = value.GetType().GetField(value.ToString()); + if (fi != null) + { + var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); + return attributes.Length > 0 && !string.IsNullOrEmpty(attributes[0].Description) ? attributes[0].Description : value.ToString(); + } + } + + return string.Empty; + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} \ No newline at end of file diff --git a/Source/Wif.Utilities/Extensions/EnumExtensions.cs b/Source/Wif.Utilities/Extensions/EnumExtensions.cs index 08156c3..dcc60da 100644 --- a/Source/Wif.Utilities/Extensions/EnumExtensions.cs +++ b/Source/Wif.Utilities/Extensions/EnumExtensions.cs @@ -42,21 +42,20 @@ public static string GetDescription(this Enum enumSubitem) { try { - var strValue = enumSubitem.ToString(); - var fieldInfo = enumSubitem.GetType().GetField(strValue); - var attribute = fieldInfo.GetCustomAttribute(false); - if (attribute != null) + if (enumSubitem == null) { - var da = attribute; - return da.Description; + return string.Empty; } + + var strValue = enumSubitem.ToString(); + FieldInfo fieldInfo = enumSubitem.GetType().GetField(strValue); + var attribute = fieldInfo.GetCustomAttribute(false); + return attribute != null ? attribute.Description : enumSubitem.ToString(); } catch (Exception ex) { - throw new Exception("分解对象值出错", ex); + throw new Exception($"分解对象{enumSubitem}值出错:{ex.Message}", ex); } - - return "未知属性名称"; } /// @@ -171,10 +170,14 @@ public static T ToEnum(this object value) where T : struct, IConvertible public static T ToEnum(this string value) where T : struct, IConvertible { if (!Enum.TryParse(value, true, out T result)) - return default; + { + return default(T); + } if (!Enum.IsDefined(typeof(T), result)) - return default; + { + return default(T); + } return result; } diff --git a/Source/Wif.Utilities/Extensions/TaskExtensions.cs b/Source/Wif.Utilities/Extensions/TaskExtensions.cs index 5dac196..dcf4645 100644 --- a/Source/Wif.Utilities/Extensions/TaskExtensions.cs +++ b/Source/Wif.Utilities/Extensions/TaskExtensions.cs @@ -1,12 +1,11 @@ /************************************************************************** -* File Name:TaskExtensions.cs -* Description:TaskExtensions.cs class description... -* Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved. -* Creator:Leo Yang -* Create Time:2020/12/15 -*Project Address:https://github.com/LeoYang-Chuese/wif -**************************************************************************/ - + * File Name:TaskExtensions.cs + * Description:TaskExtensions.cs class description... + * Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved. + * Creator:Leo Yang + * Create Time:2020/12/15 + *Project Address:https://github.com/LeoYang-Chuese/wif + **************************************************************************/ using System; using System.Threading.Tasks; @@ -18,7 +17,33 @@ namespace Frontier.Wif.Utilities.Extensions /// public static class TaskExtensions { - #region Methods + /// + /// 支持工作任务和同步执行完成委托的扩展。 + /// + /// 工作任务。 + /// 工作任务结束后的完成方法。 + /// 完成方法是否在UI线程执行,默认在UI线程执行。 + /// The + public static Task ContinueWithRun(this Task workTask, Action completedAction, bool runCompletedActionInUIThread = true) + { + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; + + return workTask.ContinueWith(unusedTask => completedAction(), taskScheduler); + } + + /// + /// 支持工作任务和同步执行完成委托的扩展。 + /// + /// 工作任务。 + /// 工作任务结束后的完成方法。 + /// 完成方法是否在UI线程执行,默认在UI线程执行。 + /// The + public static Task ContinueWithRun(this Task workTask, Action completedAction, bool runCompletedActionInUIThread = true) + { + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; + + return workTask.ContinueWith(unusedTask => completedAction(unusedTask.Result), taskScheduler); + } /// /// 延时异步执行方法。 @@ -33,16 +58,13 @@ public static void DelayRun(this Action action, int delayTime) /// /// 支持异步执行工作委托和同步执行完成委托的扩展。 /// - /// The action - /// The completedAction - /// The runCompletedActionInUIThread - /// The - public static Task RunAsync(this Action workAction, Action completedAction, - bool runCompletedActionInUIThread = true) + /// The action + /// The completedAction + /// The runCompletedActionInUIThread + /// The + public static Task RunAsync(this Action workAction, Action completedAction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; return Task.Run(workAction).ContinueWith(unusedTask => completedAction(), taskScheduler); } @@ -51,16 +73,13 @@ public static Task RunAsync(this Action workAction, Action completedAction, /// 支持异步执行工作委托和同步执行完成委托的扩展。 /// /// - /// The action - /// The completedFunction - /// The runCompletedActionInUIThread - /// The - public static Task RunAsync(this Action workAction, Func completedFunction, - bool runCompletedActionInUIThread = true) + /// The action + /// The completedFunction + /// The runCompletedActionInUIThread + /// The + public static Task RunAsync(this Action workAction, Func completedFunction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; return Task.Run(workAction).ContinueWith(unusedTask => completedFunction(), taskScheduler); } @@ -69,16 +88,13 @@ public static Task RunAsync(this Action workAction, Func /// - /// The function - /// The completedAction - /// The runCompletedActionInUIThread - /// The - public static Task RunAsync(this Func workFunction, Action completedAction, - bool runCompletedActionInUIThread = true) + /// The function + /// The completedAction + /// The runCompletedActionInUIThread + /// The + public static Task RunAsync(this Func workFunction, Action completedAction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; var task = Task.Run(workFunction); task.ContinueWith(unusedTask => completedAction(task.Result), taskScheduler); @@ -90,17 +106,13 @@ public static Task RunAsync(this Func workFunction, A /// /// /// - /// The workFunction - /// The completedAction - /// The runCompletedActionInUIThread - /// The - public static Task RunAsync(this Func workFunction, - Func completedAction, - bool runCompletedActionInUIThread = true) + /// The workFunction + /// The completedAction + /// The runCompletedActionInUIThread + /// The + public static Task RunAsync(this Func workFunction, Func completedAction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; return Task.Run(workFunction).ContinueWith(workTask => completedAction(workTask.Result), taskScheduler); } @@ -108,39 +120,37 @@ public static Task RunAsync(this Func /// 支持异步执行工作委托和同步执行完成委托的扩展。 /// - /// The workTask - /// The completedAction - /// The runCompletedActionInUIThread - /// The - public static Task RunAsync(this Task workTask, Action completedAction, - bool runCompletedActionInUIThread = true) + /// The workTask + /// The completedAction + /// The runCompletedActionInUIThread + /// The + public static Task RunAsync(this Task workTask, Action completedAction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; if (workTask.Status == TaskStatus.Created) + { workTask.Start(); + } return workTask.ContinueWith(unusedTask => completedAction(), taskScheduler); } /// - /// 支持工作任务和同步执行完成委托的扩展。 + /// 支持异步执行工作委托和同步执行完成委托的扩展。 /// - /// The action - /// The completedAction - /// The runCompletedActionInUIThread - /// The - public static Task ContinueWithRun(this Task workTask, Action completedAction, - bool runCompletedActionInUIThread = true) + /// 工作任务。 + /// 工作方法结束后的完成方法。 + /// 完成方法是否在UI线程执行,默认在UI线程执行。 + /// The + public static Task RunAsync(this Task workTask, Action completedAction, bool runCompletedActionInUIThread = true) { - var taskScheduler = runCompletedActionInUIThread - ? TaskScheduler.FromCurrentSynchronizationContext() - : TaskScheduler.Current; + TaskScheduler taskScheduler = runCompletedActionInUIThread ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current; + if (workTask.Status == TaskStatus.Created) + { + workTask.Start(); + } - return workTask.ContinueWith(unusedTask => completedAction(), taskScheduler); + return workTask.ContinueWith(unusedTask => completedAction(workTask.Result), taskScheduler); } - - #endregion } } \ No newline at end of file