【问题标题】:How to get specific data from custom attribute on multiple properties如何从多个属性的自定义属性中获取特定数据
【发布时间】:2015-09-28 08:13:53
【问题描述】:

我是属性新手,所以我试图实现的目标可能是不可能的。据我了解,属性是用于在编译时将数据绑定到特定的方法、属性、类等。

我的属性很简单,定义如下:

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

我有两个属性使用相同的自定义属性,如下所示:

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

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

这一切都很好,很花哨,但我正在尝试从另一种方法访问这些属性的属性,并根据属性的值设置某些数据。

这是我现在正在做的事情:

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
}

问题是something 总是被设置为“B”,我知道这是由于循环属性。我只是不确定如何访问与特定属性的属性关联的值。我有一种感觉,有一种我没有看到的明显的痛苦方式。

我尝试过使用StackFrame,但在我现在所在的位置附近结束。

注意:使用 .Net 4.0。

注意2:MyMethod 是我无法编辑的界面的一部分,因此我无法传递任何参数或任何东西。

感谢任何帮助。

【问题讨论】:

  • 注意,指定arrtibute时可以去掉属性名的“Attribute”部分:[NowThatsAn(HeresMyString = "A" )]

标签: c# .net properties attributes


【解决方案1】:

如果您传递特定属性的名称,您将能够获取正确的属性值:

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") 返回A

【讨论】:

  • 啊,这是一个优雅的解决方案......但是 MyMethod 是我无法编辑的界面的一部分,因此我无法将任何参数传递给它。
  • @Josh,如果方法现在没有特定属性,那么它不应该为每个属性做一些事情吗?伪代码foreach(prop in props) { something = prop.attribute(NowThatsAnAttribute).HeresMyString; DoStuff(prop.Name, something);}
【解决方案2】:

反射还为您提供属性的名称。

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;
        }
    }
}

您还可以将信息添加到字典中:

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

获取一些道具的价值

string value = dict["ThingyA"];

【讨论】:

    【解决方案3】:

    你可以做一个这样的通用方法:

        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;
        }
    

    然后你可以这样称呼它:

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

    所以你的“MyMethod”可能看起来像这样:

    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
    }
    

    这将允许您重用相同的方法来获取不同类的不同属性(或通过跳过第二个参数直接在类上的属性)上的不同属性的属性值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-29
      • 2020-05-08
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多