web-dev-qa-db-ja.com

メソッドの属性の値を読み取る

メソッド内から属性の値を読み取ることができる必要がありますが、どうすればよいですか?

[MyAttribute("Hello World")]
public void MyMethod()
{
    // Need to read the MyAttribute attribute and get its value
}
59
Coppermill

GetCustomAttributesオブジェクトで MethodBase 関数を呼び出す必要があります。
MethodBaseオブジェクトを取得する最も簡単な方法は、 _MethodBase.GetCurrentMethod_ を呼び出すことです。 ([MethodImpl(MethodImplOptions.NoInlining)]を追加する必要があることに注意してください)

例えば:

_MethodBase method = MethodBase.GetCurrentMethod();
MyAttribute attr = (MyAttribute)method.GetCustomAttributes(typeof(MyAttribute), true)[0] ;
string value = attr.Value;    //Assumes that MyAttribute has a property called Value
_

次のようにMethodBaseを手動で取得することもできます(これにより高速になります)。

_MethodBase method = typeof(MyClass).GetMethod("MyMethod");
_
74
SLaks
[MyAttribute("Hello World")]
public int MyMethod()
{
var myAttribute = GetType().GetMethod("MyMethod").GetCustomAttributes(true).OfType<MyAttribute>().FirstOrDefault();
}
30
Nagg

利用可能な答えはほとんど時代遅れです。

これが現在のベストプラクティスです。

class MyClass
{

  [MyAttribute("Hello World")]
  public void MyMethod()
  {
    var method = typeof(MyClass).GetRuntimeMethod(nameof(MyClass.MyMethod), new Type[]{});
    var attribute = method.GetCustomAttribute<MyAttribute>();
  }
}

これにはキャストが不要で、使用してもかなり安全です。

.GetCustomAttributes<T>を使用して、1つのタイプのすべての属性を取得することもできます。

16
Mafii

構築時にデフォルトの属性値をプロパティ(この例ではName)に保存する場合、静的な属性ヘルパーメソッドを使用できます。

using System;
using System.Linq;

public class Helper
{
    public static TValue GetMethodAttributeValue<TAttribute, TValue>(Action action, Func<TAttribute, TValue> valueSelector) where TAttribute : Attribute
    {
        var methodInfo = action.Method;
        var attr = methodInfo.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
        return attr != null ? valueSelector(attr) : default(TValue);
    }
}

使用法:

var name = Helper.GetMethodAttributeValue<MyAttribute, string>(MyMethod, x => x.Name);

私の解決策は、次のようにデフォルト値が属性の構築時に設定されることに基づいています:

internal class MyAttribute : Attribute
{
    public string Name { get; set; }

    public MyAttribute(string name)
    {
        Name = name;
    }
}
0
Mikael Engver

上記の@Mikael Engverのようなセットアップを実装し、複数の使用を許可する場合。すべての属性値のリストを取得するためにできることは次のとおりです。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCase : Attribute
{
    public TestCase(string value)
    {
        Id = value;
    }

    public string Id { get; }        
}   

public static IEnumerable<string> AutomatedTests()
{
    var Assembly = typeof(Reports).GetTypeInfo().Assembly;

    var methodInfos = Assembly.GetTypes().SelectMany(m => m.GetMethods())
        .Where(x => x.GetCustomAttributes(typeof(TestCase), false).Length > 0);

    foreach (var methodInfo in methodInfos)
    {
        var ids = methodInfo.GetCustomAttributes<TestCase>().Select(x => x.Id);
        yield return $"{string.Join(", ", ids)} - {methodInfo.Name}"; // handle cases when one test is mapped to multiple test cases.
    }
}
0
Hoang Minh