いつ、どこで書いたかすっかり忘れたけれど、
頭の片隅から消えないうちに書き留めておきたいと思います。
上から順に以下の物を作っていきます。
- カスタム属性
- 拡張メソッド
- Enumの定義
- 使用感
はじめは、準備から
1. カスタム属性
Ready.cs
using System;
[AttributeUsage( AttributeTargets.Field )]
public class SubValueAttribute : Attribute
{
public SubValueAttribute( object value )
{
this.SubValue = value;
}
public object SubValue { get; private set; }
}
作りはシンプルで、Attributeを継承したクラスを作り、アクセサとなるプロパティとミューテータを用意してあげればいいだけです。
今回はEnumのフィールドに付けたいので適用対象を「AttributeTargets.Field」としています。
2. 拡張メソッド
Ready.cs
using System.Linq;
using System.Reflection;
public static class EnumEx
{
public static T ToSubValue<T>( this Enum enm )
{
return (T) enm.GetType()
.GetRuntimeField( enm.ToString() )
.GetCustomAttributes( typeof( SubValueAttribute ), false )
.Cast<SubValueAttribute>()
.Single()
.SubValue;
}
}
長々とチェーンメソッドで書いていますが、やっている事はフィールドに設定した属性の値を任意(T)の型にキャストして返しているだけです。
3. Enumの定義
TrySample.cs
// こんな形でEnumに属性を付けます。
enum Example
{
[SubValue( "ABCDEFG" )]
StringValue = 0,
[SubValue( 12345 )]
IntValue,
[SubValue( new[] { "A", "B", "C" } )]
ArrayValue,
}
作っておいた属性を装着して、設定値を定義しておきます。
ここまでが準備で、後はこれらを使うだけになります。
4. 使用感
TrySample.cs
static void Main()
{
// こんな感じで取れます
string stringValue = Example.StringValue.ToSubValue<string>();
int intValue = Example.IntValue.ToSubValue<int>();
string[] arrayValue = Example.ArrayValue.ToSubValue<string[]>();
// 出力
Console.WriteLine( "StringValue \t= {0}", stringValue );
Console.WriteLine( "IntValue \t= {0}", intValue );
Console.WriteLine( "ArrayValue \t= {0},{1},{2}", arrayValue[0], arrayValue[1], arrayValue[2] );
// 結果:
// StringValue = ABCDEFG
// IntValue = 12345
// ArrayValue = A,B,C
}
拡張メソッドをジェネリックにしていますが、「毎回毎回、型を指定するのがめんどう!」「そんなに汎用性を求めてない!」という方は、必要に応じてカスタム属性と拡張メソッドをstring型やint型で型を限定して作って置くのもいいかもしれません。
その際はこんな感じなると思います。
Ready.cs
using System;
using System.Linq;
using System.Reflection;
// カスタム属性
[AttributeUsage( AttributeTargets.Field )]
public class StringAttribute : Attribute
{
public StringAttribute( string value )
{
this.String = value;
}
public string String { get; private set; }
}
// 拡張メソッド
public static class EnumEx
{
public static string ToStringFromSubValue( this Enum enm )
{
return enm.GetType()
.GetRuntimeField( enm.ToString() )
.GetCustomAttributes( typeof( StringAttribute ), false )
.Cast<StringAttribute>()
.Single()
.String;
}
}
そうすれば、多少なりコーディングが楽なるかも?
TrySample.cs
enum Example
{
[StringValue( "ABCDEFG" )]
StringValue = 0,
}
static void Main()
{
// こんな感じで取れます
//string stringValue = Example.StringValue.ToSubValue<string>();
string stringValue = Example.StringValue.ToStringFromSubValue();
// 出力
Console.WriteLine( "StringValue \t= {0}", stringValue );
// 結果:
// StringValue = ABCDEFG
}
もっとスッキリさせたいが、力量不足なのでこの辺で妥協してます。