0

I'm new to attributes so what I'm trying to achieve might not be possible. From my understanding, attributes are used to bind data at compile time to specific methods, properties, classes, etc.

My attribute is very simple and defined as follows:

public class NowThatsAnAttribute : Attribute
{
    public string HeresMyString { get; set; }
}

I have two properties that are using the same custom attribute like so:

public class MyClass
{
    [NowThatsAnAttribute(HeresMyString = "A" )]
    public string ThingyA
    {
        get;
        set;
    }

    [NowThatsAnAttribute(HeresMyString = "B" )]
    public string ThingyB
    {
        get;
        set;
    }
}

That is all working fine and dandy, but I am trying to access the attributes of these properties from another method and set certain data based on the attribute's value.

Here is what I am doing right now:

private void MyMethod()
{
    string something = "";

    var props = typeof (MyClass).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(NowThatsAnAttribute)));

    //this is where things get messy
    //here's sudo code of what I want to do
    //I KNOW THIS IS NOT VALID SYNTAX
    foreach(prop in props)
    {
        //my first idea was this
        if(prop.attribute(NowThatsAnAttribute).HeresMyString == "A")
        {
            something = "A";
        } 
        else if(prop.attribute(NowThatsAnAttribute).HeresMyString == "B")
        {
            something = "B";
        }

        //my second idea was this
        if(prop.Name == "ThingyA")
        {
            something = "A";
        } 
        else if(prop.Name == "ThingyB")
        {
            something = "B";
        }
    }

    //do stuff with something
}

The problem is that something is always being set to "B" which I know is due to looping through the properties. I'm just unsure how to access the value associated with the attribute of a specific property. I have a feeling there's a painfully obvious way of doing this that I'm just not seeing.

I've tried using the StackFrame but ended in near the same spot I'm at now.

NOTE: Using .Net 4.0.

NOTE2: MyMethod is part of an interface which I am unable to edit so I can't pass in any parameters or anything.

Any help is appreciated.

1
  • Note that you can drop the "Attribute" part of the attribute name when specifying the arrtibute: [NowThatsAn(HeresMyString = "A" )] Commented Jul 9, 2015 at 19:45

3 Answers 3

1

if you pass a name of specific property, you will be able to take correct attribute value:

private string MyMethod(string propName)
{
    PropertyInfo pi = typeof (MyClass).GetProperty(propName);
    if (pi == null)
        return null;
    var a = (NowThatsAnAttribute)pi.GetCustomAttribute(typeof(NowThatsAnAttribute));
    if (a!=null)
        return a.HeresMyString;
    return null;
}

MyMethod("ThingyA") returns A

Sign up to request clarification or add additional context in comments.

2 Comments

Ahh that is an elegant solution... however MyMethod is part of an interface which I cannot edit so I can't pass any parameters into it.
@Josh, if method doesn't now specific property then shouldn't it do stuff for each property? pseudocode foreach(prop in props) { something = prop.attribute(NowThatsAnAttribute).HeresMyString; DoStuff(prop.Name, something);}
0

Reflection also gives you the names of the properties.

Type t = typeof(MyClass);
PropertyInfo[] props = t.GetProperties();
foreach (PropertyInfo p in props) {
    NowThatsAnAttribute attr = p.GetCustomAttributes(false)
        .OfType<NowThatsAnAttribute>()
        .FirstOrDefault();
    if (attr != null) {
        string propName = p.Name;
        string attrValue = attr.HeresMyString;
        switch (propName) {
            case "ThingyA":
                //TODO: Do something for ThingyA
                break;
            case "ThingyB":
                //TODO: Do something for ThingyB
                break;
            default:
                break;
        }
    }
}

You could also add the info to a dictionary:

var dict = new Dictionary<string, string();
...
if (attr != null) {
    string propName = p.Name;
    string attrValue = attr.HeresMyString;
    dict.Add(propName, attrValue);
}
...

Getting value of some prop

string value = dict["ThingyA"];

Comments

0

You could do a generic method like this:

    static object GetAttributeValue<T, A>(string attribName, string propName = "") where A : Attribute
    {
        object[] attribs = null;

        if (string.IsNullOrEmpty(propName))
            attribs = typeof(T).GetCustomAttributes(true);

        else
        {
            PropertyInfo pi = typeof(T).GetProperty(propName);
            if (pi == null)
                return null;
            attribs = pi.GetCustomAttributes(true);
        }

        A a = null;
        foreach (object attrib in attribs)
        {
            if (attrib is A)
            {
                a = attrib as A;
                break;
            }
        }

        if (a != null)
        {
            var prop = a.GetType().GetProperty(attribName);
            return prop.GetValue(a, null);
        }
        return null;
    }

You would then call it like this:

object value = GetPropertyAttributeValue<MyClass,NowThatsAnAttribute>("HeresMyString", "ThingyA");

So your "MyMethod" could look like this:

private void MyMethod()
{
    string something = "";

    var props = typeof (MyClass).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(NowThatsAnAttribute)));

    //this is where things get messy
    //here's sudo code of what I want to do
    //I KNOW THIS IS NOT VALID SYNTAX
    foreach(prop in props)
    {
        string attribVal = object value = GetPropertyAttributeValue<MyClass,NowThatsAnAttribute>("HeresMyString", prop.Name);
        //my first idea was this
        if(attribVal == "A")
        {
            something = "A";
        } 
        else if(attribVal == "B")
        {
            something = "B";
        }

    }

    //do stuff with something
}

This would allow you to reuse the same method to get attribute values for different attributes on different properties(or attributes directly on the class by skipping the second parameter) from different classes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.