Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Attribute Value in C# for the class property

 [System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
    sealed class ColumnName : Attribute
    {
        // See the attribute guidelines at 
        //  http://go.microsoft.com/fwlink/?LinkId=85236

        readonly string Column;

        // This is a positional argument
        public ColumnName(string columnName)
        {
            this.Column = columnName;
        }
    }

    public class Comment
    {
        [ColumnName("ID1")]
        public int Id;
        [ColumnName("NAME1")]
        public string Name;
        [ColumnName("TEST1")]
        public string Test;
    }

In this code you can see I have create a class comment which have an attribute ColumnName. ColumnName is my custom class which I used to define the attirubte.

Now I am looking for a sollution to find the ColumnName value for all the properties.

public static List<T> ExecuteReader<T>(string str)
        {
            var res = typeof(T);

            return new List<T>();
        }

I tried run some Stack Overflow code on my issue but it doesn't work well. What thing I am missing in my code?

like image 237
Anirudha Gupta Avatar asked Sep 12 '25 18:09

Anirudha Gupta


1 Answers

Given

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public sealed class ColumnNameAttribute : Attribute
{
    public readonly string Column;

    public ColumnNameAttribute(string columnName)
    {
        this.Column = columnName;
    }
}

(by convention attributes should have a name ending in Attribute, and note that I've restricted the AttributeTargets to Propertyes and Fields) you can

public static class ColumnsCache<T>
{
    public static readonly IReadOnlyDictionary<MemberInfo, string> Columns = BuildColumnsDictionary();

    public static Dictionary<MemberInfo, string> BuildColumnsDictionary()
    {
        var dict = new Dictionary<MemberInfo, string>();

        var members = typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance)
            .Where(x => x.MemberType == MemberTypes.Field || x.MemberType == MemberTypes.Property);

        foreach (MemberInfo member in members)
        {
            var attr = member.GetCustomAttribute<ColumnNameAttribute>(true);

            if (attr != null)
            {
                dict.Add(member, attr.Column);
            }
        }

        return dict;
    }
}

(note the trick: we are caching the list of column names (and of fields/properties having the ColumnNameAttribute) through the usage of a generic static class. The .NET runtime will create various distinct ColumnsCache<T1>, ColumnsCache<T2>, ColumnsCache<T3>, each one with a different dictionary of columns)

Then you can

var cols = ColumnsCache<Comment>.Columns;
var colNames = cols.Values;

The cols variable will reference a dictionary MemberInfo -> string (colum name), while the colNames is a IEnumerable<string> with only the column names. If you want to use reflection with a MemberInfo you have to check if the MemberInfo is a FieldInfo or a PropertyInfo, cast it and use the FieldInfo or PropertyInfo.

like image 185
xanatos Avatar answered Sep 15 '25 08:09

xanatos