[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?
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 Property
es and Field
s) 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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With