Skip to content

Commit

Permalink
Added EnumDescriptionTypeConverter,update EnumBindingSourceExtension、…
Browse files Browse the repository at this point in the history
…EnumExtensions and TaskExtensions.
  • Loading branch information
LeoYang06 committed Mar 8, 2024
1 parent a1a8021 commit 0b99ceb
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/// <summary>
/// Markup extension for Enum values.
/// https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
/// 枚举值绑定源的标记扩展。<remarks>参考 https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/</remarks>
/// </summary>
public class EnumBindingSourceExtension
: MarkupExtension
public class EnumBindingSourceExtension : MarkupExtension
{
#region Fields

/// <summary>
/// Defines the _enumType
/// 定义枚举类型字段。
/// </summary>
private Type _enumType;

#endregion
/// <summary>
/// Initializes a new instance of the <see cref="EnumBindingSourceExtension" /> class.
/// </summary>
public EnumBindingSourceExtension()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="EnumBindingSourceExtension" /> class.
/// </summary>
/// <param name="enumType">枚举类型。</param>
public EnumBindingSourceExtension(Type enumType)
{
EnumType = enumType;
}

#region Properties
/// <summary>
/// Initializes a new instance of the <see cref="EnumBindingSourceExtension" /> class.
/// </summary>
/// <param name="enumType">枚举类型。</param>
/// <param name="isSorted">枚举成员是否排序。</param>
public EnumBindingSourceExtension(Type enumType, bool isSorted)
{
EnumType = enumType;
IsSorted = isSorted;
}

/// <summary>
/// Gets or sets the type of the Enum.
/// 获取或设置枚举类型。
/// </summary>
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

/// <summary>
/// Initializes a new instance of the <see cref="EnumBindingSourceExtension"/> class.
/// 获取或设置是否排序,开启后获取EnumOrderAttribute值,若Attribute未设置,按照成员定义顺序排序。
/// </summary>
public EnumBindingSourceExtension()
{
}
public bool IsSorted { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="EnumBindingSourceExtension"/> class.
/// 返回用作此标记扩展的目标属性值的对象。
/// </summary>
/// <param name="enumType">The type of the Enum.</param>
public EnumBindingSourceExtension(Type enumType)
{
EnumType = enumType;
}

#endregion

#region Methods

/// <summary>
/// The ProvideValue
/// </summary>
/// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
/// <returns>The values of the Enum.</returns>
/// <param name="serviceProvider">为标记扩展提供服务的对象。</param>
/// <returns>枚举的所有值。</returns>
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<EnumOrderAttribute>()
}).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
/// <summary>
/// 表示在EnumBindingExtension中定义枚举成员顺序的特性。
/// </summary>
[AttributeUsage(AttributeTargets.All, Inherited = false)]
public sealed class EnumOrderAttribute : Attribute
{
/// <summary>
/// 有参构造函数。
/// </summary>
/// <param name="order">枚举成员序号。</param>
public EnumOrderAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}

/// <summary>
/// 获取枚举成员序号。
/// </summary>
public int Order { get; }
}
}
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// 表示枚举值转描述值的类型转换器。
/// </summary>
public class EnumDescriptionTypeConverter : EnumConverter
{
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public EnumDescriptionTypeConverter(Type type) : base(type)
{
}

/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value"></param>
/// <param name="destinationType"></param>
/// <returns></returns>
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);
}
}
}
25 changes: 14 additions & 11 deletions Source/Wif.Utilities/Extensions/EnumExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DescriptionAttribute>(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<DescriptionAttribute>(false);
return attribute != null ? attribute.Description : enumSubitem.ToString();
}
catch (Exception ex)
{
throw new Exception("分解对象值出错", ex);
throw new Exception($"分解对象{enumSubitem}值出错:{ex.Message}", ex);
}

return "未知属性名称";
}

/// <summary>
Expand Down Expand Up @@ -171,10 +170,14 @@ public static T ToEnum<T>(this object value) where T : struct, IConvertible
public static T ToEnum<T>(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;
}
Expand Down
Loading

0 comments on commit 0b99ceb

Please sign in to comment.