Я не собираюсь комментировать аргумент добра / зла, но я не использовал их с тех пор, как появилась Spring . Использование внедрения зависимостей в значительной степени сняло мои требования к синглтону, сервис-локаторам и фабрикам. Я считаю, что это намного более продуктивная и чистая среда, по крайней мере, для того типа работы, которую я выполняю (веб-приложения на основе Java).
I выяснил, как это сделать, не делая предположений о перечислении, имитируя функции в .Net:
public static string[] GetNames(this Enum e) {
List<string> enumNames = new List<string>();
foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)){
enumNames.Add(fi.Name);
}
return enumNames.ToArray<string>();
}
public static Array GetValues(this Enum e) {
List<int> enumValues = new List<int>();
foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)) {
enumValues.Add((int)Enum.Parse(e.GetType(), fi.Name, false));
}
return enumValues.ToArray();
}
Или, может быть, строго типизированный с использованием linq, например:
public static T[] GetEnumValues<T>()
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("Type '" + type.Name + "' is not an enum");
return (
from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
where field.IsLiteral
select (T)field.GetValue(null)
).ToArray();
}
public static string[] GetEnumStrings<T>()
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("Type '" + type.Name + "' is not an enum");
return (
from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
where field.IsLiteral
select field.Name
).ToArray();
}
Я считаю, что это то же самое, что и в .NET Compact Framework. Если мы сделаем предположение, что ваши значения перечисления начинаются с 0 и используют каждое значение до тех пор, пока их диапазон не превысит диапазон, следующий код должен работать.
public static IList<int> GetEnumValues(Type oEnumType)
{
int iLoop = 0;
bool bDefined = true;
List<int> oList = new List<int>();
//Loop values
do
{
//Check if the value is defined
if (Enum.IsDefined(oEnumType, iLoop))
{
//Add item to the value list and increment
oList.Add(iLoop);
++iLoop;
}
else
{
//Set undefined
bDefined = false;
}
} while (bDefined);
//Return the list
return oList;
}
Очевидно, вы можете настроить код, чтобы возвращать имена перечислений или сопоставлять различные шаблоны, например побитовые значения.
Вот альтернативная версия метода, который возвращает IList
.
public static IList<T> GetEnumValues<T>()
{
Type oEnumType;
int iLoop = 0;
bool bDefined = true;
List<T> oList = new List<T>();
//Get the enum type
oEnumType = typeof(T);
//Check that we have an enum
if (oEnumType.IsEnum)
{
//Loop values
do
{
//Check if the value is defined
if (Enum.IsDefined(oEnumType, iLoop))
{
//Add item to the value list and increment
oList.Add((T) (object) iLoop);
++iLoop;
}
else
{
//Set undefined
bDefined = false;
}
} while (bDefined);
}
//Return the list
return oList;
}