4

編集: 言い換えたほうがいいです: カスタム属性を使用して、クラス プロパティの GET 実装を / にシフトするにはどうすればよいですか? (インスタンス化変数 (クラス名、プロパティ名) を属性に追加しましたが、もちろんこれらを自動的に取得したいと思います。)

Public Class CustomClass
    <CustomAttributeClass(ClassName:="CustomClass", PropertyName = "SomeProperty")> _
    Public Property SomeProperty() as String
        Get() as String
            //This implementation should be handled by the attribute class
        End Get

        Set(Byval value as String)
            Me._someProperty = value
        End Set
    End Property
End Class

古い質問:

クラスのカスタム プロパティ属性を作成したいと考えています。Attribute から派生したクラスを作成し、プロパティをその属性で「マーク」できますが、ここからどこに行けばよいでしょうか?

属性値に基づいてデータをすばやく取得できるリポジトリがあります。属性のプロパティの動作を一般化したいのですが、ここからどうすればよいかわかりません...どんな助けも大歓迎です!

Public Class CustomDataAttribute : Inherits Attribute
    Private _name As String

    Public Sub New(ByVal name As String)
        Me.Name = name
    End Sub

    Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            Me._name = value
        End Set
    End Property
End Class


Public Class CustomClass
    <CustomDataAttribute(Name:="CustomField")> _ 
    Public Property CustomField()
    End Property
End Class
4

3 に答える 3

2

属性を検出するには、Reflection を使用する必要があります。あなたの場合、PropertyInfo.GetCustomAttributes() から取得します。

属性を使用する上で難しいのは、それらを実際に使用するための適切な実行モデルを見つけることです。オブジェクトをシリアル化するコンパイラ、デザイナー、またはクラスのようなものは明らかです。属性の使いやすさは、そこから急速に低下します。仮想プロパティが実際に必要な属性を使用しようとすると、ほとんどの場合、間違った選択になります。属性値の取得は非常にコストがかかり、プロパティ値の取得よりも桁違いにコストがかかります。リフレクション コードが人間の時間で実行される場合 (コンパイラなど)、または利点やオーバーヘッドと比較してコストが重要でない場合 (あらゆる種類の I/O 操作で一般的) にのみ、それらを使用してください。

于 2010-03-06T16:16:39.647 に答える
2

コメントから前の回答まで、.NET 属性は希望するほど柔軟ではないことがわかると思います。

あなたは「onGet や onSet のようないくつかのイベントを持つ基本プロパティ属性はありませんか?」と尋ねました。 - 番号; メソッドであろうとクラスであろうと、属性にはターゲットとの組み込みの相互作用がありません。実際、実行時に属性のターゲットが何であるかを知ることさえできません。最初にターゲット(クラス、メソッド、プロパティなど)を知ってから、それを装飾する属性を照会する必要があります。

次に、クエリを実行するまで属性は実際には作成されません。を呼び出すGetCustomAttributesと、ランタイム システムはアセンブリ メタデータを評価し、指定された属性をインスタンス化します。2 回続けて呼び出すと、同じ属性のセットが 2 つ取得されます。

他の質問に戻ります。属性で装飾されたプロパティがいつ設定または取得されるかを知りたい場合はINotifyPropertyChanged、関連するすべてのクラスに実装する必要があります。その属性でマークされたプロパティをすべてのクラスで検索するコードを記述します。アセンブリの読み込み時に、PropertyChangedイベントを起動する必要のあるコードに接続する対話機能を構築します。set(そして、それは操作について通知するだけで、 ではありませんget。)

これが役立つかどうかはわかりませんが、どうぞ。:-)

于 2010-03-06T16:47:43.223 に答える
0

これは、リフレクションを使用するときにカスタム属性を処理するのに役立つクラスです。タイプをパラメーターとしてcontructorに渡します。

public class AttributeList : List<Attribute>
{
    /// <summary>
    /// Gets a list of custom attributes
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static AttributeList GetCustomAttributeList(ICustomAttributeProvider propertyInfo)
    {
        var result = new AttributeList();
        result.AddRange(propertyInfo.GetCustomAttributes(false).Cast<Attribute>());
        return result;
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T FindAttribute<T>() where T : Attribute
    {
        return (T)Find(x => typeof(T).IsAssignableFrom(x.GetType()));
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public List<T> FindAllAttributes<T>() where T : Attribute
    {
        return new List<T>(FindAll(x => typeof(T).IsAssignableFrom(x.GetType())).Cast<T>());
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public List<T> FindAllAttributes<T>(Type implementsType) where T : Attribute
    {
        return new List<T>(FindAll(x => implementsType.IsAssignableFrom(x.GetType())).Cast<T>());
    }

    public bool IsAttributeSet<T>() where T : Attribute
    {
        return FindAttribute<T>() != null;
    }

    public TValue GetValueFromAttributeOrDefault<TAttr, TValue>(Func<TAttr, TValue> func, TValue defaultValue) 
        where TAttr : Attribute
    {
        var attribute = FindAttribute<TAttr>();
        return attribute == null ? 
            defaultValue : 
            func(attribute);
    }
}

于 2010-03-18T03:04:43.293 に答える