简体   繁体   中英

C# Accessing custom attribute of owner object

How can I access the custom attribute of the parent or owner object. Look at the FieldInfo property of the SQLFieldInfo struct

Here's a more detailed program that will compile and run that shows what I need.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        Employee myclass = new Employee();

        // Load from sql server...
        myclass.Name = "Alain";
        myclass.Age = 51;
        //----

        MessageBox.Show(myclass.Name.ToString()); // Should return Alain
        MessageBox.Show(myclass.Age.FieldInfo.Type.ToString()); // Should output "int"
    }
}

// This next class is generated by a helper exe that reads SQL table design and create the class from it
[SQLTableAttribute(DatabaseName = "Employees", Schema = "dbo", TableName = "Employees")]
public class Employee
{
    [SQLFieldAttribute(FieldName = "ID", Type = SqlDbType.Int)]
    public SQLFieldInfo<int> ID { get; set; }

    [SQLFieldAttribute(FieldName = "Name", Type = SqlDbType.NVarChar, Size = 200)]
    public SQLFieldInfo<String> Name { get; set; }

    [SQLFieldAttribute(FieldName = "Age", Type = SqlDbType.Int)]
    public SQLFieldInfo<int> Age { get; set; }
}


public struct SQLFieldInfo<T>
{

    private readonly T value;

    public SQLFieldInfo(T Value) 
    {
        this.value = Value;
    }


    public static implicit operator SQLFieldInfo<T>(T Value)
    {
        return new SQLFieldInfo<T>(Value);
    }


    public T Value
    {
        get
        {
            return this.value;
        }
    }


    public override string ToString()
    {
        return this.value.ToString();
    }


    public SQLFieldAttribute FieldInfo
    {
        get
        {
            // Need to retreive the attribute class of the parent or declaring member

            return null;
        }
    }
}

// Holds the sql field information
public class SQLFieldAttribute : Attribute
{
    public string FieldName { get; set; }
    public SqlDbType Type { get; set; }
    public bool AllowNull { get; set; }
    public int Size { get; set; }
}

// Holds the sql table information
public class SQLTableAttribute : Attribute
{
    public string DatabaseName { get; set; }
    public string Schema { get; set; } = "dbo";
    public string TableName { get; set; }
}

Thank you!

Alain

First, MSDN is your friend.

Then, if you want to get the attributes for ancestors just specify true in the inherit flag of the method:

var attribute = typeof(A).GetProperty("myprop").GetCustomAttributes(true)
                       .OfType<MycustomAttrib>().FirstOrDefault();

My data class is as follows (should be fairly translatable to A above):

public class Foo 
{
    [Argument(Help = "Name", AssignmentDelimiter = "=")]
    public string Name
    {
        get;
        set;
    }
}

A helper class is responsible of reading attribute values of objects:

static public string GetCommandLineDelimiter<T>(Expression<Func<T>> property)
{
    if(property != null)
    {
        var memberExpression = (MemberExpression)property.Body;
        string propertyName = memberExpression.Member.Name;
        PropertyInfo prop = typeof(Arguments).GetProperty(propertyName);
        if(prop != null)
        {
            object[] dbFieldAtts = prop.GetCustomAttributes(typeof(ArgumentAttribute), true);
            if(dbFieldAtts.Length > 0)
            {
                return ((ArgumentAttribute)dbFieldAtts[0]).AssignmentDelimiter;
            }
        }
    }
    return null;
}

To use it, simply:

string delimiter = GetCommandLineDelimiter(() => myObject.Name);

That will get the attribute value of AssignmentDelimiter on property Name, ie "=".

This works. I am doing a lazy initialization of a reference to the custom attribute by using reflection to look at all the properties of all the types .

public class MycustomAttribAttribute : Attribute
{
    public MycustomAttribAttribute(string name)
    {
        this.Name=name;
    }
    public string Name { get; private set; }
}
class A
{
    public A() { MyProp=new B(); }
    [MycustomAttrib(name: "OK")]
    public B MyProp { get; set; }
}


class B
{
    private static Lazy<MycustomAttribAttribute> att = new Lazy<MycustomAttribAttribute>(() =>
    {
        var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes;

        foreach(var item in types)
        {
            foreach(var prop in item.DeclaredProperties)
            {
                var attr = prop.GetCustomAttributes(typeof(MycustomAttribAttribute), false);
                if(attr.Length>0)
                {
                    return attr[0] as MycustomAttribAttribute;
                }
            }
        }
        return null;
    });
    public string MyProp2
    {
        get
        {
            return att.Value.Name;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Finds the attribute reference and returns "OK"
        string name = (new A()).MyProp.MyProp2;
        // Uses the stored attribute reference to return "OK"
        string name2 = (new A()).MyProp.MyProp2;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM