各メンバーにカスタム属性が適用されている列挙型があります。各属性に保存されている値を取得するにはどうすればよいですか?
今私はこれをします:
var attributes = typeof ( EffectType ).GetCustomAttributes ( false );
foreach ( object attribute in attributes )
{
GPUShaderAttribute attr = ( GPUShaderAttribute ) attribute;
if ( attr != null )
return attr.GPUShader;
}
return 0;
別の問題は、見つからない場合、何を返す必要がありますか? 0はimplcityを任意の列挙型に変換できますよね?それが私がそれを返した理由です。
言及し忘れましたが、上記のコードはすべての列挙型メンバーに対して0を返します。
リフレクションを使用しなければならないので、あなたがしようとしていることを行うのは少し面倒です:
public GPUShaderAttribute GetGPUShader(EffectType effectType)
{
MemberInfo memberInfo = typeof(EffectType).GetMember(effectType.ToString())
.FirstOrDefault();
if (memberInfo != null)
{
GPUShaderAttribute attribute = (GPUShaderAttribute)
memberInfo.GetCustomAttributes(typeof(GPUShaderAttribute), false)
.FirstOrDefault();
return attribute;
}
return null;
}
これは、GPUShaderAttribute
の列挙値でマークアップされたものに関連するEffectType
のインスタンスを返します。 EffectType
enumの特定の値で呼び出す必要があります。
GPUShaderAttribute attribute = GetGPUShader(EffectType.MyEffect);
属性のインスタンスを取得したら、個々の列挙値でマークアップされた特定の値を取得できます。
一般的な方法を使用してみてください
属性:
class DayAttribute : Attribute
{
public string Name { get; private set; }
public DayAttribute(string name)
{
this.Name = name;
}
}
列挙:
enum Days
{
[Day("Saturday")]
Sat,
[Day("Sunday")]
Sun,
[Day("Monday")]
Mon,
[Day("Tuesday")]
Tue,
[Day("Wednesday")]
Wed,
[Day("Thursday")]
Thu,
[Day("Friday")]
Fri
}
一般的な方法:
public static TAttribute GetAttribute<TAttribute>(this Enum value) where TAttribute : Attribute { var enumType = value.GetType(); var name = Enum.GetName(enumType, value); return enumType.GetField(name).GetCustomAttributes(false).OfType<TAttribute>().SingleOrDefault(); }
呼び出す:
static void Main(string[] args)
{
var day = Days.Mon;
Console.WriteLine(day.GetAttribute<DayAttribute>().Name);
Console.ReadLine();
}
結果:
月曜
ジェネリックでこれを行う別の方法があります。
public static T GetAttribute<T>(Enum enumValue) where T: Attribute
{
T attribute;
MemberInfo memberInfo = enumValue.GetType().GetMember(enumValue.ToString())
.FirstOrDefault();
if (memberInfo != null)
{
attribute = (T) memberInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault();
return attribute;
}
return null;
}
GPUShaderAttribute
を想定:
[AttributeUsage(AttributeTargets.Field,AllowMultiple =false)]
public class GPUShaderAttribute: Attribute
{
public GPUShaderAttribute(string value)
{
Value = value;
}
public string Value { get; internal set; }
}
次に、列挙値とGPUShaderAttribute
オブジェクトのディクショナリを返すいくつかの汎用メソッドを作成できます。
/// <summary>
/// returns the attribute for a given enum
/// </summary>
public static TAttribute GetAttribute<TAttribute>(IConvertible @enum)
{
TAttribute attributeValue = default(TAttribute);
if (@enum != null)
{
FieldInfo fi = @enum.GetType().GetField(@enum.ToString());
attributeValue = fi == null ? attributeValue : (TAttribute)fi.GetCustomAttributes(typeof(TAttribute), false).DefaultIfEmpty(null).FirstOrDefault();
}
return attributeValue;
}
次に、このメソッドでセット全体を返します。
/// <summary>
/// Returns a dictionary of all the Enum fields with the attribute.
/// </summary>
public static Dictionary<Enum, RAttribute> GetEnumObjReference<TEnum, RAttribute>()
{
Dictionary<Enum, RAttribute> _dict = new Dictionary<Enum, RAttribute>();
Type enumType = typeof(TEnum);
Type enumUnderlyingType = Enum.GetUnderlyingType(enumType);
Array enumValues = Enum.GetValues(enumType);
foreach (Enum enumValue in enumValues)
{
_dict.Add(enumValue, GetAttribute<RAttribute>(enumValue));
}
return _dict;
}
文字列値だけが必要な場合は、少し異なるルートをお勧めします。
/// <summary>
/// Returns the string value of the custom attribute property requested.
/// </summary>
public static string GetAttributeValue<TAttribute>(IConvertible @enum, string propertyName = "Value")
{
TAttribute attribute = GetAttribute<TAttribute>(@enum);
return attribute == null ? null : attribute.GetType().GetProperty(propertyName).GetValue(attribute).ToString();
}
/// <summary>
/// Returns a dictionary of all the Enum fields with the string of the property from the custom attribute nulls default to the enumName
/// </summary>
public static Dictionary<Enum, string> GetEnumStringReference<TEnum, RAttribute>(string propertyName = "Value")
{
Dictionary<Enum, string> _dict = new Dictionary<Enum, string>();
Type enumType = typeof(TEnum);
Type enumUnderlyingType = Enum.GetUnderlyingType(enumType);
Array enumValues = Enum.GetValues(enumType);
foreach (Enum enumValue in enumValues)
{
string enumName = Enum.GetName(typeof(TEnum), enumValue);
string decoratorValue = Common.GetAttributeValue<RAttribute>(enumValue, propertyName) ?? enumName;
_dict.Add(enumValue, decoratorValue);
}
return _dict;
}
私はこれを試していませんが、このブログの投稿はあなたが探しているものを説明しているようです: Enumeration attribute help
ターゲットの列挙値のFieldInfo要素を見つける別の方法を思いつきました。列挙値を文字列に変換して見つけるのは間違っていると感じたため、LINQを使用してフィールドリストをチェックすることを選択しました。
Type enumType = value.GetType();
FieldInfo[] fields = enumType.GetFields();
FieldInfo fi = fields.Where(tField =>
tField.IsLiteral &&
tField.GetValue(null).Equals(value)
).First();
だから私はすべて一緒に輝いています:
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
Type enumType = value.GetType();
FieldInfo[] fields = enumType.GetFields();
FieldInfo fi = fields.Where(tField =>
tField.IsLiteral &&
tField.GetValue(null).Equals(value)
).First();
// If we didn't get, return null
if (fi == null) return null;
// We found the element (which we always should in an enum)
// return the attribute if it exists.
return (TAttribute)(fi.GetCustomAttribute(typeof(TAttribute)));
}