今日も自分の学びに対するメモです。Azure Functions を書いていると必ず出てくる Attributes ですが、カスタムの Attributes を書くときにどんなコードになるのか知りたかったので調べて書いてみました。
題材として、被告人がいて、自分がズラかどうかを告白するのですが、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] 私ははげていません。
カツラが検出されました。 メーカー: アデランス
めでたしめでたし。