単純な列挙型があります
public enum TestEnum
{
TestOne = 3,
TestTwo = 4
}
var testing = TestEnum.TestOne;
そして、リフレクションを介してその値(3)を取得したいです。これを行う方法に関するアイデアはありますか?
すばらしい質問です。
質問のシナリオは次のとおりです。
いくつかの未知の列挙型といくつかの未知の値があり、その未知の値の基礎となる数値を取得したい。
これは、リフレクションを使用してこれを行う1行の方法です。
object underlyingValue = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
値がTestEnum.TestTwo
である場合、value.GetType()
はtypeof(TestEnum)
と等しくなり、Enum.GetUnderlyingType(value.GetType())
はtypeof(int)
と等しくなり、値は3になります。 (ボックス化;値のボックス化とボックス化解除の詳細については、 http://msdn.Microsoft.com/en-us/library/yz2be5wk.aspx を参照してください)。
なぜそのようなコードを書く必要があるのでしょうか?私の場合、ビューモデルからモデルに値をコピーするルーチンがあります。 ASP.NET MVCプロジェクトのすべてのハンドラーで、Microsoftテンプレートによって生成されたハンドラーのセキュリティ問題を持たないハンドラーを作成するための非常にクリーンでエレガントなアーキテクチャーの一部としてこれを使用します。
このモデルは、Entity Frameworkによってデータベースから生成され、int型のフィールドが含まれています。ビューモデルにはいくつかの列挙型のフィールドがあります。それをRecordStatusと呼びましょう。これをプロジェクトの他の場所で定義しました。私のフレームワークで列挙型を完全にサポートすることにしました。しかし、モデルのフィールドのタイプとビューモデルの対応するフィールドのタイプとの間に不一致があります。私のコードはこれを検出し、上記のワンライナーに似たコードを使用して列挙型をintに変換します。
System.Enumヘルパーを使用できます。
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);
}
出力
3
4
完全なコード: C#でReflectionを使用して列挙値を取得する方法
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";
}
なぜ反射が必要なのですか?
int value = (int)TestEnum.TestOne;
要件については、すでに指摘されているように簡単です。 enumオブジェクトをintにキャストするだけで、enumの数値を取得できます。
int value = (int) TestEnum.TestOne;
ただし、enum値を|とミックスダウンする必要がある場合(ビットごとのOR)例:.
var value = TestEnum.TestOne | TestEnum.TestTwo;
混合ダウン値が表すオプションを取得したい場合は、これを行う方法があります(注:これは、ビット単位の操作を利用することを目的としたint値で表される列挙型用です):
最初に、ディクショナリで列挙値とその値を取得します。
var all_options_dic = typeof(TestEnum).GetEnumValues().Cast<object>().ToDictionary(k=>k.ToString(), v=>(int) v);
ディクショナリをフィルタリングして、ミックスダウンオプションのみを返します。
var filtered = all_options_dic.Where(x => (x.Value & (int) options) != 0).ToDictionary(k=>k.Key, v=>v.Value);
オプションでロジックを実行します。例えばそれらの印刷、リストへの変換など。
foreach (var key in filtered.Keys)
{
Console.WriteLine(key + " = " + filtered[key]);
}
お役に立てれば。
以下を試してください:
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)));
反射の必要はありません:
int value = (int)TestEnum.TestOne;
こんにちは、この代替手段があります:
Type typevar = GetType([YourEnum])
そして... ...名前付きの配列を返すtypevar.GetEnumNames
を使用して名前を取得し、値付きの配列を返すtype.GetEnumValues
を使用して値を取得できます。
私の場合、問題はアセンブリからタイプを取得する+記号のためにMyEnumが見つからないことでした(2行目):
var dll = System.Reflection.Assembly.LoadFile("pathToDll");
Type myEnum = dll.GetType("namespace+MyEnum");
System.Array myEnumValues = System.Enum.GetValues(myEnum);
単純な。
var value = propertyInfo.GetValue(obj); // this return TestOne or TestTwo
var enumValue = Convert.ChangeType(value, typeof(int)); // this return 3 or 4