36

プロパティに適用できる次のカスタム属性があります。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IdentifierAttribute : Attribute
{
}

例えば:

public class MyClass
{
    [Identifier()]
    public string Name { get; set; }

    public int SomeNumber { get; set; }
    public string SomeOtherProperty { get; set; }
}

異なるタイプのプロパティに識別子属性を追加できる他のクラスもあります。

public class MyOtherClass
{
    public string Name { get; set; }

    [Identifier()]
    public int SomeNumber { get; set; }

    public string SomeOtherProperty { get; set; }
}

次に、消費クラスでこの情報を取得できるようにする必要があります。例えば:

public class TestClass<T>
{
    public void GetIDForPassedInObject(T obj)
    {
        var type = obj.GetType();
        //type.GetCustomAttributes(true)???
    }
}

これについて行く最良の方法は何ですか?[Identifier()]フィールドのタイプ(int、stringなど)と実際の値を取得する必要があります。これは明らかにタイプに基づいています。

4

4 に答える 4

50

次のようなもので、これは属性を持つ最初のプロパティのみを使用します。もちろん、複数のプロパティに配置することもできます。

    public object GetIDForPassedInObject(T obj)
    {
        var prop = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                   .FirstOrDefault(p => p.GetCustomAttributes(typeof(IdentifierAttribute), false).Count() ==1);
        object ret = prop !=null ?  prop.GetValue(obj, null) : null;

        return ret;
    }  
于 2010-07-20T10:58:50.257 に答える
3
public class TestClass<T>
{
    public void GetIDForPassedInObject(T obj)
    {
        PropertyInfo[] properties =
            obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);            

        PropertyInfo IdProperty = (from PropertyInfo property in properties
                           where property.GetCustomAttributes(typeof(Identifier), true).Length > 0
                           select property).First();

         if(null == IdProperty)
             throw new ArgumentException("obj does not have Identifier.");

         Object propValue = IdProperty.GetValue(entity, null)
    }
}
于 2010-07-20T11:06:35.383 に答える
3

少し遅れていますが、列挙型(任意のオブジェクトでもかまいません)と拡張機能を使用してdescription属性値を取得するために行ったことがあります(これは任意の属性のジェネリックである可能性があります):

public enum TransactionTypeEnum
{
    [Description("Text here!")]
    DROP = 1,

    [Description("More text here!")]
    PICKUP = 2,

    ...
}

値の取得:

var code = TransactionTypeEnum.DROP.ToCode();

すべての列挙型をサポートする拡張機能:

public static string ToCode(this TransactionTypeEnum val)
{
    return GetCode(val);
}

public static string ToCode(this DockStatusEnum val)
{
    return GetCode(val);
}

public static string ToCode(this TrailerStatusEnum val)
{
    return GetCode(val);
}

public static string ToCode(this DockTrailerStatusEnum val)
{
    return GetCode(val);
}

public static string ToCode(this EncodingType val)
{
    return GetCode(val);
}

private static string GetCode(object val)
{
    var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);

    return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}
于 2018-03-29T15:53:17.443 に答える
-1

これがより現実的な例です。拡張メソッドを使用して、プロパティに有効なMajorおよびMinorVersionを持つFieldMetaDataAttribute(ソースコードベースのカスタム属性)が含まれているかどうかを確認します。一般的に興味深いのは、親クラスタイプとGetPropertiesを使用してProperyInfoを取得し、次にGetCustomAttributeを使用してこの特殊なケースで属性FieldMetaDataAttributeを取得する部分です。このコードを使用して、カスタム属性を取得するためのより一般的な方法を実行する方法を学びます。もちろん、これを洗練して、クラスインスタンスの任意のプロパティの特定の属性を取得する一般的なメソッドを作成することもできます。

        /// <summary>
    /// Executes the action if not the field is deprecated 
    /// </summary>
    /// <typeparam name="TProperty"></typeparam>
    /// <typeparam name="TForm"></typeparam>
    /// <param name="form"></param>
    /// <param name="memberExpression"></param>
    /// <param name="actionToPerform"></param>
    /// <returns>True if the action was performed</returns>
    public static bool ExecuteActionIfNotDeprecated<TForm, TProperty>(this TForm form, Expression<Func<TForm, TProperty>> memberExpression, Action actionToPerform)
    {
        var memberExpressionConverted = memberExpression.Body as MemberExpression;
        if (memberExpressionConverted == null)
            return false; 

        string memberName = memberExpressionConverted.Member.Name;


        PropertyInfo matchingProperty = typeof(TForm).GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .FirstOrDefault(p => p.Name == memberName);
        if (matchingProperty == null)
            return false; //should not occur

        var fieldMeta = matchingProperty.GetCustomAttribute(typeof(FieldMetadataAttribute), true) as FieldMetadataAttribute;
        if (fieldMeta == null)
        {
            actionToPerform();
            return true;
        }

        var formConverted = form as FormDataContract;
        if (formConverted == null)
            return false;

        if (fieldMeta.DeprecatedFromMajorVersion > 0 && formConverted.MajorVersion > fieldMeta.DeprecatedFromMajorVersion)
        {
            //major version of formConverted is deprecated for this field - do not execute action
            return false;
        }

        if (fieldMeta.DeprecatedFromMinorVersion > 0 && fieldMeta.DeprecatedFromMajorVersion > 0
                                                     && formConverted.MinorVersion >= fieldMeta.DeprecatedFromMinorVersion
                                                     && formConverted.MajorVersion >= fieldMeta.DeprecatedFromMajorVersion)
            return false; //the field is expired - do not invoke action 
        actionToPerform();
        return true;
    }
于 2019-11-27T10:55:33.057 に答える