LoginSignup
8
9

More than 5 years have passed since last update.

カツラ検出プログラムで学ぶ C# Attributes

Posted at

今日も自分の学びに対するメモです。Azure Functions を書いていると必ず出てくる Attributes ですが、カスタムの Attributes を書くときにどんなコードになるのか知りたかったので調べて書いてみました。

GH.png

題材として、被告人がいて、自分がズラかどうかを告白するのですが、Attributes によってそれを見破るプログラムを作ってみました。

カスタムAttributes の定義

Attributes の定義は次のようになっていて。単なる普通のクラスです。コンストラクタを書いておくと、クラスやメソッドに対して、Attributes をつけられるようになる様子です。 AttributeUsage でAttribute であることを明確にします。Attribute 名は、Attribute の接尾句を省略したものになるので、ここでは、[GHDetect] という Attribute が使えるようになります。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method,
        AllowMultiple = true, Inherited = false)]
    public class GHDetectAttribute : Attribute
    {
        private string maker;
        private bool isWig;
        public GHDetectAttribute(bool isWig, string maker)
        {
            this.maker = maker;
            this.isWig = isWig;
        }
        public string Maker {  get { return this.maker; } }
        public bool IsWig { get { return this.isWig; } }
    }

カスタムAttributes の適用

全く同じクラスを定義して、ほぼ同じ結果を返すメソッドを定義した2つのクラスを定義します。片方には、カツラをtrue にし、そのカツラのメーカー名の情報を持たせておきます。一方は、カツラではないということにしておきましょう。

  public interface Accused
    {
        void Execute();
    }

    [GHDetect(true, "アデランス")]
    public class Takeru : Accused
    {
        public void Execute()
        {
            Console.WriteLine("[Takeru] 私ははげていません。");
        }
    }
    [GHDetect(false, null)]
    public class Tsuyoshi : Accused
    {
        public void Execute()
        {
            Console.WriteLine("[Tsuyoshi] 私ははげていません。");
        }
    }

Attribute の取得

クラスの型がわかれば、定義された Attribute が取得できます。ちなみに、メソッドに定義した場合は、リフレクションを使ってメソッドを取得してから、Attributes が取れる様子です。まずは簡単のためクラスのみでやってみます。 MemberInfo を渡すと、Attribute を返すようにしています。ちなみに、Attribute[] を返すようにもできます。(複数のアトリビュートがある場合)。クラスのタイプだったり、MethodInfo を引数として渡すことができます。

        static Attribute DetectGH(MemberInfo info)
        {
            Attribute detector = Attribute.GetCustomAttribute(
                info, typeof(GHDetectAttribute));
            return detector;
        }

Attribute が取れれば、これは単なるクラスですので、値を取得してロジックを書きます。

    static void Execute(Accused accused)
        {
            var accusedAttribute = DetectGH(accused.GetType()) as GHDetectAttribute;
            if (accusedAttribute.IsWig)
            {
                accused.Execute();
                Console.WriteLine($"カツラが検出されました。 メーカー: {accusedAttribute.Maker}");
            } else
            {
                accused.Execute();
                Console.WriteLine("本当に地毛のようです。");
            }
        }

これでカツラかどうかを判別できるようになるはずです。では次のメインを書いて実行。

        static void Main(string[] args)
        {
            Accused tsuyoshi = new Tsuyoshi();
            Execute(tsuyoshi);
            Console.ReadLine();
            Accused takeru = new Takeru();
            Execute(takeru);
            Console.ReadLine();

        }

実行

[Tsuyoshi] 私ははげていません。
本当に地毛のようです。

[Takeru] 私ははげていません。
カツラが検出されました。 メーカー: アデランス

めでたしめでたし。

Resource

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9