aboutsummaryrefslogtreecommitdiffstats
path: root/src/qtvstools.core/Common/EnumExt.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtvstools.core/Common/EnumExt.cs')
-rw-r--r--src/qtvstools.core/Common/EnumExt.cs199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/qtvstools.core/Common/EnumExt.cs b/src/qtvstools.core/Common/EnumExt.cs
new file mode 100644
index 00000000..4ebcdacb
--- /dev/null
+++ b/src/qtvstools.core/Common/EnumExt.cs
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt VS Tools.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace QtVsTools.Common
+{
+ /// <summary>
+ /// Extended enum support:
+ /// * Customized cast of enum values to arbitrary types
+ /// </summary>
+ public static class EnumExt
+ {
+ /// <summary>
+ /// Wrapper for enum cast values.
+ /// </summary>
+ /// <typeparam name="T">Type of cast output</typeparam>
+ /// <remarks>
+ /// Cast attributes associated with enum values must implement this interface.
+ /// </remarks>
+ public interface ICast<T>
+ {
+ T Value { get; }
+ }
+
+ /// <summary>
+ /// String cast attribute associated to an enum value.
+ /// </summary>
+ /// <example>
+ /// enum Foobar {
+ /// Foo,
+ /// [EnumExt.String("Bahr")] Bar
+ /// }
+ /// </example>
+ [AttributeUsage(AttributeTargets.All)]
+ public sealed class StringAttribute : Attribute, ICast<string>
+ {
+ public string Value { get; private set; }
+ public StringAttribute(string str) { Value = str; }
+ }
+
+ /// <summary>
+ /// Cast enum value to type T.
+ /// </summary>
+ /// <typeparam name="T">Cast output type.</typeparam>
+ /// <param name="value">Input enum value.</param>
+ /// <returns>
+ /// Value of type T associated to the enum value by an Attribute implementing
+ /// ICast<typeparamref name="T"/>. If no attribute is found, returns a default value.
+ /// </returns>
+ /// <example>
+ /// enum Foobar
+ /// {
+ /// Foo,
+ /// [EnumExt.String("Bahr")] Bar
+ /// }
+ /// Foobar foo = Foobar.Foo;
+ /// Foobar bar = Foobar.Bar;
+ /// string fooCastString = foo.Cast<string>(); // "Foo"
+ /// string barCastString = bar.Cast<string>(); // "Bahr"
+ /// string fooToString = foo.ToString(); // "Foo"
+ /// string barToString = bar.ToString(); // "Bar"
+ /// </example>
+ public static T Cast<T>(this Enum value)
+ {
+ if (FindCastAttrib<T>(value) is ICast<T> cast)
+ return cast.Value;
+ else
+ return Default<T>(value);
+ }
+
+ /// <summary>
+ /// Compare enum value with instance/value of type T.
+ /// </summary>
+ /// <typeparam name="T">Cast/comparison type.</typeparam>
+ /// <param name="valueT">Instance/value of type T to compare with.</param>
+ /// <param name="valueEnum">Enum value to compare with.</param>
+ /// <returns>true if cast of valueEnum is equal to valueT, false otherwise</returns>
+ public static bool EqualTo<T>(this T valueT, Enum valueEnum)
+ {
+ return valueT.Equals(valueEnum.Cast<T>());
+ }
+
+ /// <summary>
+ /// Convert type T to enum
+ /// </summary>
+ public static bool TryCast<T, TEnum>(this T valueT, out TEnum value) where TEnum : struct
+ {
+ value = default(TEnum);
+ IEnumerable<Enum> enumValues = Enum.GetValues(typeof(TEnum)).OfType<Enum>()
+ .Where((Enum valueEnum) => valueEnum.Cast<T>().Equals(valueT));
+ if (enumValues.Any())
+ value = (TEnum)Enum.ToObject(typeof(TEnum), enumValues.FirstOrDefault());
+ return enumValues.Any();
+ }
+
+ /// <summary>
+ /// Get list of values of enum type converted to type T
+ /// </summary>
+ public static IEnumerable<T> GetValues<T>(Type enumType)
+ {
+ return Enum.GetValues(enumType).OfType<Enum>()
+ .Select((Enum value) => value.Cast<T>());
+ }
+
+ /// <summary>
+ /// Default cast of enum value to type T.
+ /// </summary>
+ /// <typeparam name="T">Cast output type.</typeparam>
+ /// <param name="value">Input enum value.</param>
+ /// <returns>
+ /// Default value of type T associated with the enum value:
+ /// * if T is string: returns the enum value name as string;
+ /// * if T is an integer type: returns the underlying enum integer value;
+ /// * otherwise: default value for type T (e.g. null for reference types).
+ /// </returns>
+ static T Default<T>(Enum value)
+ {
+ Type enumType = value.GetType();
+ Type baseType = Enum.GetUnderlyingType(enumType);
+ Type outputType = typeof(T);
+ if (outputType.IsAssignableFrom(enumType) || outputType.IsAssignableFrom(baseType))
+ return (T)(object)value;
+ else if (outputType == typeof(string))
+ return (T)(object)Enum.GetName(value.GetType(), value);
+ else
+ return default(T);
+ }
+
+ /// <summary>
+ /// Find cast attribute.
+ /// </summary>
+ /// <typeparam name="T">Cast output type.</typeparam>
+ /// <param name="value">Input enum value.</param>
+ /// <returns>
+ /// First cast attribute of type T found associated with the enum value, or null in case a
+ /// suitable attribute is not found.
+ /// </returns>
+ static ICast<T> FindCastAttrib<T>(Enum value)
+ {
+ Type enumType = value.GetType();
+
+ string valueName = Enum.GetName(enumType, value);
+ if (string.IsNullOrEmpty(valueName))
+ return null;
+
+ FieldInfo enumField = enumType.GetField(valueName);
+ if (enumField == null)
+ return null;
+
+ return CastAttribTypes
+ .Where(type => typeof(ICast<T>).IsAssignableFrom(type))
+ .Select(type => Attribute.GetCustomAttribute(enumField, type) as ICast<T>)
+ .FirstOrDefault();
+ }
+
+ static IEnumerable<Type> _CastAttribTypes;
+ /// <summary>
+ /// List of cast attribute types.
+ /// </summary>
+ /// <remarks>
+ /// Future cast attribute types need to be added to this list.
+ /// </remarks>
+ static IEnumerable<Type> CastAttribTypes => _CastAttribTypes
+ ?? (_CastAttribTypes = new[]
+ {
+ typeof(StringAttribute)
+ });
+
+ }
+}