Я попытаюсь дать решение относительно моего понимания проблемы.
Насколько я понимаю, OP хочет иметь универсальный метод упорядочения значений c для всех перечисляемых типов, передаваемых в атрибуте. введите и, найдя способ получить значения сравнения, используя этот атрибут.
Вот что я имею в виду:
Давайте предположим, что у нас есть атрибут, с помощью которого мы украшаем наши значения перечисления для упорядочения :
[AttributeUsage(AttributeTargets.Field)]
public class MyEnumOrderAttribute : Attribute
{
public MyEnumOrderAttribute(int order)
{
Order = order;
}
public int Order { get; set; }
}
И давайте перечислим наши перечисления, значения которых оформлены с использованием нашего атрибута:
public enum MyEnum
{
[MyEnumOrder(2)]
MyVal0 = 0,
[MyEnumOrder(1)]
MyVal1,
[MyEnumOrder(3)]
MyVal2,
[MyEnumOrder(0)]
MyVal3
}
Эти перечисления и атрибуты могут быть нашими или могут быть из сторонней сборки, и мы хотим, чтобы наш метод упорядочил значения с помощью этого атрибута, поэтому нам нужно передать тип атрибута (который уже является универсальным c параметром), и нам нужно передать функцию для получения значения сравнения из экземпляр атрибута.
Следовательно; Вот новая реализация нашего метода расширения: (Некоторые замечания по поводу того, что это метод расширения позже)
public static IEnumerable<TEnum> EnumGetOrderedValues<TEnum, TAttribute>
(this Type enumType, Func<TAttribute, IComparable> valueExtractor)
where TAttribute : Attribute
{
var fields = typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static);
var orderedValues = new List<Tuple<IComparable, TEnum>>();
foreach (var field in fields)
{
var orderAtt = field.GetCustomAttributes(typeof(TAttribute), false).SingleOrDefault() as TAttribute;
if (orderAtt != null)
{
orderedValues.Add(new Tuple<IComparable, TEnum>(valueExtractor(orderAtt), (TEnum)field.GetValue(null)));
}
}
return orderedValues.OrderBy(x => x.Item1).Select(x => x.Item2).ToList();
}
Как вы можете видеть, этот метод теперь работает с любым типом атрибута с любым типом значения, используемым для сравнения. (int, string, any IComparable)
А вот как его использовать:
var orderedValues = typeof(MyEnum).EnumGetOrderedValues<MyEnum, MyEnumOrderAttribute>(x => x.Order);
Пожалуйста, не передавайте x => x.Order
как функцию, чтобы получить значение атрибута для сравнения. Здесь мы можем передать любую реализацию.
И выходные данные для упорядоченных значений:
foreach (MyEnum orderedValue in orderedValues)
{
Console.WriteLine(orderedValue);
}
MyVal3
MyVal1
MyVal0
MyVal2
РЕДАКТИРОВАТЬ: Обратите внимание на метод, являющийся методом расширения.
Метод является расширением Type
, которое, я думаю, не является необходимым.
В настоящее время мы называем этот метод следующим образом:
typeof(MyEnum).EnumGetOrderedValues<MyEnum, MyEnumOrderAttribute>(x => x.Order);
Метод расширения уже принимает тип enum в своем первом Параметр generi c, и вызов этого метода для любого типа (typeof (string)?) возможен, что может сбить с толку.
Почему бы не использовать его как метод stati c? Если бы это было возможно, будучи расширением, вызывать этот метод для самого перечисления, как MyEnum.EnumGetOrderedValues
, это имело бы смысл. Но поскольку это невозможно, мы можем просто изменить его на метод stati c:
public static IEnumerable<TEnum> EnumGetOrderedValues<TEnum, TAttribute>
(Func<TAttribute, IComparable> valueExtractor)
where TAttribute : Attribute
и получить тип перечисления внутри, используя typeof(TEnum)
Надеюсь, это поможет