Reputation: 6702
I have a simple Enum
public enum TestEnum
{
TestOne = 3,
TestTwo = 4
}
var testing = TestEnum.TestOne;
And I want to retrieve its value (3) via reflection. Any ideas on how to do this?
Upvotes: 58
Views: 95457
Reputation: 176896
Full code : How to Get Enum Values with Reflection in C#
MemberInfo[] memberInfos =
typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static);
string alerta = "";
for (int i = 0; i < memberInfos.Length; i++) {
alerta += memberInfos[i].Name + " - ";
alerta += memberInfos[i].GetType().Name + "\n";
}
Upvotes: 26
Reputation: 850
If you have loaded an assembly in reflection-only context the methods GetValue and GetValues don't work. But we can use another approach:
var val = typeof(MyEnum).GetFields()
.Where(fi => fi.IsLiteral && fi.Name == "TestOne")
.Select(fi => fi.GetRawConstantValue())
.First();
Upvotes: 7
Reputation: 193
Get enum int value via reflection using this method
protected static object PropertyValue(object obj, string propertyName)
{
var property = obj.GetType().GetProperty(propertyName);
if(property == null)
throw new Exception($"{propertyName} not found on {obj.GetType().FullName}");
if (property.PropertyType.IsEnum)
return (int) property.GetValue(obj);
return property.GetValue(obj);
}
Upvotes: 1
Reputation: 2501
You can use the Gethashkey function to get the value of enum with an unknown type.
Enum.Parse(enumType, enumvalue).GetHashCode();
More details
Getting enum type dynamically
private static Type GetEnumType(string enumName)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var type = assembly.GetType(enumName);
if (type == null)
continue;
if (type.IsEnum)
return type;
}
return null;
}
Reading enum values
Enum.GetValues(enumType);
I hope it helps someone!
Upvotes: 1
Reputation: 19340
There must be a motivation to ask a question like this. Here I have one real life scenario with good motivation to do something like this and the solution to this problem.
Motivation
2 assemblies with circular references. One reference is hard reference, i.e. <Reference . . .>
tag in project file. And a soft reference in opposite direction. assembly1
must call some object, some method in assembly2
. Method's argument is enum
Here is the code that will get enum value. The assembly is already loaded at the time of calling this method because instance of the object containing method already loaded
Solution
internal static object GetEnumValue(string assemblyName, string enumName, string valueName) // we know all these
{
var assembly = Assembly.Load(assemblyName);
var converter = new EnumConverter(assembly.GetType(enumName));
object enumVal = converter.ConvertFromString(valueName);
return enumVal;
}
And the usage
dynamic myInstance = GetInstanceOfKnownObject(.......); // this preloads assembly for first time. All sequential loads are easy
dynamic enumArg = GetEnumValue("assemblyName", "assembly2.namespace1.EnumName", "enumValueName"); // important to load into 'dynamic', not 'object'
myInstance.MyMethod(enumArg);
Bottom line - it is really useful when one assembly has no idea (and can't have knowledge) of the other assembly internals.
Upvotes: -1
Reputation: 841
You can use the System.Enum helpers:
System.Type enumType = typeof(TestEnum);
System.Type enumUnderlyingType = System.Enum.GetUnderlyingType(enumType);
System.Array enumValues = System.Enum.GetValues(enumType);
for (int i=0; i < enumValues.Length; i++)
{
// Retrieve the value of the ith enum item.
object value = enumValues.GetValue(i);
// Convert the value to its underlying type (int, byte, long, ...)
object underlyingValue = System.Convert.ChangeType(value, enumUnderlyingType);
System.Console.WriteLine(underlyingValue);
}
Outputs
3
4
Upvotes: 47
Reputation: 889
For your requirement it's as simple as people already pointed it out. Just cast the enum object to int and you'd get the numeric value of the enum.
int value = (int) TestEnum.TestOne;
However, if there is a need to mix-down enum values with | (bitwise OR) e.g.
var value = TestEnum.TestOne | TestEnum.TestTwo;
and you wish to get what options that mixed-down value represents, here is how you could do it (note: this is for enums that represented by int values intended to take advantage of bitwise operatations) :
first, get the enum options along with their values in a dictionary.
var all_options_dic = typeof(TestEnum).GetEnumValues().Cast<object>().ToDictionary(k=>k.ToString(), v=>(int) v);
Filter the dictionary to return only the mixed-down options.
var filtered = all_options_dic.Where(x => (x.Value & (int) options) != 0).ToDictionary(k=>k.Key, v=>v.Value);
do whatever logic with your options. e.g. printing them, turning them to List, etc..:
foreach (var key in filtered.Keys)
{
Console.WriteLine(key + " = " + filtered[key]);
}
hope this helps.
Upvotes: 3
Reputation: 1855
Just simple.
var value = propertyInfo.GetValue(obj); // this return TestOne or TestTwo
var enumValue = Convert.ChangeType(value, typeof(int)); // this return 3 or 4
Upvotes: 0
Reputation: 404
In my case, the problem was MyEnum not been found due to a + sign getting type from assembly (line 2):
var dll = System.Reflection.Assembly.LoadFile("pathToDll");
Type myEnum = dll.GetType("namespace+MyEnum");
System.Array myEnumValues = System.Enum.GetValues(myEnum);
Upvotes: -1
Reputation: 11
System.Type.GetType("Namespace Name" + "." + "Class Name" + "+" + "Enum Name")
Dim fieldInfos() As System.Reflection.FieldInfo = System.Type.GetType("YourNameSpaceName.TestClass+TestEnum").GetFields
For Each f As System.Reflection.FieldInfo In fieldInfos
If f.IsLiteral Then
MsgBox(f.Name & " : " & CType(f.GetValue(Nothing), Integer) & vbCrLf)
End If
Next
Public Class TestClass
Public Enum TestEnum
val1 = 20
val2 = 30
End Enum
End Class
That works
Upvotes: 0
Reputation: 19
Hi you have this alternative:
Type typevar = GetType([YourEnum])
And then ...
...
You can get names using typevar.GetEnumNames
returning a array with names and to get values using type.GetEnumValues
, returning an array with values.
Upvotes: 0
Reputation: 2713
Try the following:
System.Array enumValues = System.Enum.GetValues(typeof(MyEnum));
Type underlyingType = System.Enum.GetUnderlyingType(MyEnum);
foreach (object enumValue in enumValues)
System.Console.WriteLine(String.Format("{0}",Convert.ChangeType(enumValue ,underlyingType)));
Upvotes: 2
Reputation: 3996
Great question Mat.
The scenario of the question is this:
You have some unknown enum type and some unknown value of that type and you want to get the underlying numeric value of that unknown value.
This is the one-line way of doing this using reflection:
object underlyingValue = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
If value happens to be TestEnum.TestTwo
, then value.GetType()
would be equal to typeof(TestEnum)
, Enum.GetUnderlyingType(value.GetType())
would be equal to typeof(int)
and value would be 3 (boxed; see http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx for more details about boxing and unboxing values).
Why would one ever need to write such code? In my case, I have a routine that copies values from a viewmodel to a model. I use this in all my handlers in an ASP.NET MVC project as part of a very clean and elegant architecture for writing handlers that do not have the security problems the handlers generated by the Microsoft templates do.
The model is generated by the Entity Framework from the database and it contains a field of type int. The viewmodel has a field of some enum type, let's call it RecordStatus, which I have defined elsewhere in my project. I decided to support enums fully in my framework. But now there is a mismatch between the type of the field in the model and the type of the corresponding field in the viewmodel. My code detects this and converts the enum to an int using the code similar to the one-liner given above.
Upvotes: 72
Reputation: 19
Or, if you needed the actual enum object (of type TestEnum) :
MemberInfo[] memberInfos = typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static);
string alerta = "";
for (int i = 0; i < memberInfos.Length; i++) {
alerta += memberInfos[i].Name + " - ";
/* alerta += memberInfos[i].GetType().Name + "\n"; */
// the actual enum object (of type MyEnum, above code is of type System.Reflection.RuntimeFieldInfo)
object enumValue = memberInfos[i].GetValue(0);
alerta += enumValue.ToString() + "\n";
}
Upvotes: 0
Reputation: 190945
Why do you need reflection?
int value = (int)TestEnum.TestOne;
Upvotes: 3
Reputation: 158309
No need for reflection:
int value = (int)TestEnum.TestOne;
Upvotes: -1