やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#ツアー 属性(アトリビュート)

 取得が面倒。

成果物

情報源

コード

 属性の定義。

NameAttribute.cs

class NameAttribute : System.Attribute
{
    public string Name { get; private set; }
    public NameAttribute(string name) => Name = name;
}

 属性の使用。

[Name("CCC")]
class C {}

 属性の取得。

class Main
{
    public void Run()
    {
        ShowCClassAttrs();
    }
    void ShowCClassAttrs() {
        foreach (NameAttribute attr in GetClassAttrs<C,NameAttribute>()) {
            Console.WriteLine($"{attr.Name}");
        }
    }
    A[] GetClassAttrs<T,A>() {
        object[] objs = typeof(T).GetCustomAttributes(typeof(A), false);
        return Array.ConvertAll(objs, o => {
            return (A)o;
        });
    }
}

 実行結果は以下。

CCC

全メンバ取得

[Name("Class")]
class C
{
    [Name("Field")]
    private int i;
    [Name("Property")]
    private int I { get; set; }
    [Name("Method")]
    private void M() {}
    [Name("コンストラクタ")]
    public C() {}
    [Name("デストラクタ")]
    ~C() {}
    [Name("列挙体の型定義")]
    enum E { e }
    [Name("構造体の型定義")]
    struct S {}
    [Name("デリゲートの型定義")]
    delegate void D();
}
using System;
using System.Collections.Generic;
using System.Reflection;

class Main
{
    public void Run()
    {
        ShowCClassAttrs();
        ShowCClassMemberAttrs();
    }
    void ShowCClassAttrs() {
        foreach (NameAttribute attr in GetClassAttrs<C,NameAttribute>()) {
            Console.WriteLine($"{attr.Name}");
        }
    }
    A[] GetClassAttrs<T,A>() {
        object[] objs = typeof(T).GetCustomAttributes(typeof(A), false);
        return Array.ConvertAll(objs, o => {
            return (A)o;
        });
    }
    void ShowCClassMemberAttrs() {
        foreach (NameAttribute attr in GetMemberAttrs<C,NameAttribute>()) {
            Console.WriteLine($"{attr.Name}");
        }
    }
    A[] GetMemberAttrs<T,A>() {
        List<A> result = new List<A>();
        MemberInfo[] members = typeof(T).GetMembers(
            BindingFlags.Public | BindingFlags.NonPublic |
            BindingFlags.Instance | BindingFlags.Static |
            BindingFlags.DeclaredOnly);
        foreach (MemberInfo m in members)
        {
            object[] objs = m.GetCustomAttributes(typeof(A), false);
            result.AddRange(Array.ConvertAll(objs, o => {
                return (A)o;
            }));
        }
        return result.ToArray();
    }
}

 実行結果は以下。

Class
Method
デストラクタ
コンストラクタ
Property
Field
列挙体の型定義
構造体の型定義
デリゲートの型定義

所感

 これにてMicrosoftC#ツアー完了。なんか所々チュートリアルと被ってた感ある。ツアーでは基礎の基礎に触れた。地味に知らない重要なこともあったので、やって良かった。

 ただ、ジェネリクスとかLINQとか、まだまだ重要なものに触れ足りない。MSDNのリンクは新章がまだまだあるので、順次やっていく。その前にツアー記事をまとめよう。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux