8

次のような属性クラスに Guid プロパティが必要です。

public class SomeAttribute : Attribute {
    private Guid foreignIdentificator;
    public Guid ForeignIdentificator {
        get { return this.foreignIdentificator; }
        set { this.foreignIdentificator = value; }
    }
}

しかし、属性定義では、定数であるプリミティブ型のみを使用できます (理由は理解できますし、理にかなっています)。回避策は、「ForeignIdentificator」を文字列として定義し、実行時に Guid を作成することです。

public class SomeAttribute : Attribute {
    private string foreignIdentificator;
    public string ForeignIdentificator {
        get { return this.foreignIdentificator; }
        set { this.foreignIdentificator = value; }
    }
    public Guid ForeignIdentificatorGuid {
        get { return new Guid( ForeignIdentificator ); }
    }
}

残念ながら、型安全性のチェックを失いました。「ForeignIdentificator」プロパティには任意の文字列値を含めることができ、Guid の作成中に、コンパイル時ではなく実行時に例外がスローされます。

コンパイラは、「Guid 互換性」のために「System.Runtime.InteropServices.GuidAttribute」の文字列値をチェックすることを知っています。このチェックはまさに​​私が必要としているものですが、このチェックがコンパイラでハードコーディングされているのか、それとも明示的に定義できるのか (およびその方法) はわかりません。

属性の「Guid互換性」チェックを保護する方法を知っていますか? または、別の方法で、属性でタイプセーフな Guid 定義に到達する方法は? ありがとう。

4

2 に答える 2

9

私は過去にあなたの正確な問題に遭遇しました。GUID を文字列として渡すように要求しただけです... VS GUID ジェネレーター ツールが提供するデフォルトの方法 (*F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4)。私たちは基本的にあなたがしたことをしました。プラグイン アーキテクチャで使用しているため、このインターフェイスを使用するのはお客様です。マイクロソフトが同じことをする必要があるときに何をするかを見ると、彼らはそれをしています。

このようにしても問題ありませんでした。これを現場の問題として見たことは一度もありません。

ただし、コンシューマーを混乱させないように、その文字列フィールドに GUID という名前を付けることをお勧めします。必要な形式がわからない場合に備えて、いくつかのドキュメントを追加します。

これを見たときも同じ反応がありました...しかし、タイプセーフな解決策がないように見えるので、先に進みました。

于 2008-11-28T13:26:37.617 に答える
5

属性パラメータは定数でなければなりません。ルールを破ると、C# コンパイラで次のエラーが発生します。

属性引数は、定数式、typeof 式、または属性パラメーター タイプの配列作成式でなければなりません

C# には GUID リテラルがないため、GUID を別の形式 (文字列など) にエンコードする必要があります。ただし、完全に海にいるわけではありません。アトリビュートに、必要な形式の ctor を持たせることができます。と同じ ctors の例を次に示しますSystem.Guid

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class MyGuidAttribute : Attribute
{
    public Guid Guid { get; private set; }

    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified array
    //     of bytes.
    //
    // Parameters:
    //   b:
    //     A 16 element byte array containing values with which to initialize the GUID.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     b is null.
    //
    //   System.ArgumentException:
    //     b is not 16 bytes long.
    public MyGuidAttribute(byte[] b)
    {
        this.Guid = new Guid(b);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the value represented
    //     by the specified string.
    //
    // Parameters:
    //   g:
    //     A System.String that contains a GUID in one of the following formats ('d'
    //     represents a hexadecimal digit whose case is ignored): 32 contiguous digits:
    //     dddddddddddddddddddddddddddddddd -or- Groups of 8, 4, 4, 4, and 12 digits
    //     with hyphens between the groups. The entire GUID can optionally be enclosed
    //     in matching braces or parentheses: dddddddd-dddd-dddd-dddd-dddddddddddd -or-
    //     {dddddddd-dddd-dddd-dddd-dddddddddddd} -or- (dddddddd-dddd-dddd-dddd-dddddddddddd)
    //     -or- Groups of 8, 4, and 4 digits, and a subset of eight groups of 2 digits,
    //     with each group prefixed by "0x" or "0X", and separated by commas. The entire
    //     GUID, as well as the subset, is enclosed in matching braces: {0xdddddddd,
    //     0xdddd, 0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} All braces, commas,
    //     and "0x" prefixes are required. All embedded spaces are ignored. All leading
    //     zeroes in a group are ignored.  The digits shown in a group are the maximum
    //     number of meaningful digits that can appear in that group. You can specify
    //     from 1 to the number of digits shown for a group. The specified digits are
    //     assumed to be the low order digits of the group.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     g is null.
    //
    //   System.FormatException:
    //     The format of g is invalid.
    //
    //   System.OverflowException:
    //     The format of g is invalid.
    public MyGuidAttribute(string g)
    {
        this.Guid = new Guid(g);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified integers
    //     and byte array.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The remaining 8 bytes of the GUID.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     d is null.
    //
    //   System.ArgumentException:
    //     d is not 8 bytes long.
    public MyGuidAttribute(int a, short b, short c, byte[] d)
    {
        this.Guid = new Guid(a, b, c, d);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified integers
    //     and bytes.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The next byte of the GUID.
    //
    //   e:
    //     The next byte of the GUID.
    //
    //   f:
    //     The next byte of the GUID.
    //
    //   g:
    //     The next byte of the GUID.
    //
    //   h:
    //     The next byte of the GUID.
    //
    //   i:
    //     The next byte of the GUID.
    //
    //   j:
    //     The next byte of the GUID.
    //
    //   k:
    //     The next byte of the GUID.
    public MyGuidAttribute(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
    {
        this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified unsigned
    //     integers and bytes.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The next byte of the GUID.
    //
    //   e:
    //     The next byte of the GUID.
    //
    //   f:
    //     The next byte of the GUID.
    //
    //   g:
    //     The next byte of the GUID.
    //
    //   h:
    //     The next byte of the GUID.
    //
    //   i:
    //     The next byte of the GUID.
    //
    //   j:
    //     The next byte of the GUID.
    //
    //   k:
    //     The next byte of the GUID.
    [CLSCompliant(false)]
    public MyGuidAttribute(uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
    {
        this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k);
    }
}
于 2008-11-28T13:46:20.323 に答える