potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C# クラスに属性でIIDを持たせる

C#ではカスタム属性でクラス自体にIIDを持たせられます。ただし静的メンバーより動作は遅く、Guidのような非標準型は属性定義時の引数に渡せないようです。

using System.Reflection;

Console.WriteLine(IIDAttribute.Of<ClassWithIPersistIID>()?.ToString("B") ?? "(未定義)");
Console.WriteLine(IIDAttribute.Of<ClassWithoutIID>()?.ToString("B") ?? "(未定義)");
//> {0000010c-0000-0000-c000-000000000046}
//> (未定義)

class IIDAttribute : Attribute
{
    public readonly Guid Value;
    public IIDAttribute(string iid)
    {
        Value = Guid.ParseExact(iid, "D");
    }

    // コードが冗長なのでメソッドを用意します。
    public static Guid? Of<T>()
    {
        return typeof(T).GetCustomAttribute<IIDAttribute>()?.IID;
    }
}

// IID_IPersist
[IID("0000010c-0000-0000-C000-000000000046")]
class ClassWithIPersistIID
{
}

class ClassWithoutIID
{
}

属性クラスに属性を持たせることで適用対象も指定できます。

// クラスのみに適用可能
// 複数指定は拒否
// 派生クラスやオーバーライドへの継承は拒否
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
class IIDAttribute : Attribute
{
    ...
}

他の使い方は公式ドキュメントや実際の属性のソースコードを参照ください。