在不知道属性类型的情况下从属性和列表值中获取属性值

Posted

技术标签:

【中文标题】在不知道属性类型的情况下从属性和列表值中获取属性值【英文标题】:Get attribute values from property and list values without knowing the attribute type 【发布时间】:2012-10-16 02:00:14 【问题描述】:

我想传入属性名并返回值。这将在通用工具中,并且它不知道属性类型。

更新 如果有人需要这样做,这是实际的工作代码。我需要一种方法让核心代码在不知道属性是什么的情况下解析它们。

public void LoadPropertiesToGrid(BaseGridPropertyModel model)

    foreach (PropertyInfo prop in ReflectionUtil.FindPublicPropeties(model))
    
        object editTyp = ReflectionUtil.GetPropertyAttributes(prop, "EditorType"); 
        object rowIdx = ReflectionUtil.GetPropertyAttributes(prop, "ColIndex");
        object name = ReflectionUtil.GetPropertyAttributes(prop, "Name");
        object visible = ReflectionUtil.GetPropertyAttributes(prop, "Visible");
        ConfigureColumn((string) name, (int) rowIdx, (bool) visible, (string) editTyp);
     

[Serializable]
public class CanvasPropertiesViewModel : BaseGridPropertyModel

    [PropertiesGrid(Name = "TEsting Name 0", ColIndex = 0)]
    public string StringData1  get; set; 

    [PropertiesGrid(Name = "TEsting Name 2", ColIndex = 2)]
    public string StringData2  get; set; 

    [PropertiesGrid(Name = "TEsting Name 1", ColIndex = 1)]
    public string StringData3  get; set; 

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public sealed class PropertiesGridAttribute : Attribute

    /// <summary>
    /// Editor type
    /// </summary>
    public Type EditorType  get; set; 

    /// <summary>
    /// Sets Column Index
    /// </summary>
    public int ColIndex  get; set; 

    /// <summary>
    /// Visible to Grid
    /// </summary>
    public bool Visible  get; set; 

    /// <summary>
    /// Dispaly Name of the property
    /// </summary>
    public string Name  get; set; 

public static object GetPropertyAttributes(PropertyInfo prop, string attributeName)

    // look for an attribute that takes one constructor argument
    foreach (CustomAttributeData attribData in prop.GetCustomAttributesData())
    
        string typeName = attribData.Constructor.DeclaringType.Name;
        //if (attribData.ConstructorArguments.Count == 1 && (typeName == attributeName || typeName == attributeName + "Attribute"))
        //
        //    return attribData.ConstructorArguments[0].Value;
        //
        foreach (CustomAttributeNamedArgument att in attribData.NamedArguments)
        
            if(att.GetPropertyValue<string>("MemberName") == attributeName)
            
                return att.TypedValue.Value;
            
        
    
    return null;


//PropertyExpressionParser 
public static TRet GetPropertyValue<TRet>(this object obj, string propertyPathName)

    if (obj == null)
    
        throw new ArgumentNullException("obj");
    

    string[] parts = propertyPathName.Split('.');
    string path = propertyPathName;
    object root = obj;

    if (parts.Length > 1)
    
        path = parts[parts.Length - 1];
        parts = parts.TakeWhile((p, i) => i < parts.Length - 1).ToArray();
        string path2 = String.Join(".", parts);
        root = obj.GetPropertyValue<object>(path2);
    

    var sourceType = root.GetType();
    var value = (TRet)sourceType.GetProperty(path).GetValue(root, null);
    return value;

【问题讨论】:

属性没有.Name.Value的概念。你能举个例子来显示代码示例和所需的输出吗? 相关:***.com/q/6637679 【参考方案1】:

如果你的意思是“给定一个带有一个参数的属性,给我那个值”,例如:

[DisplayName("abc")] <===== "abc"
[Browsable(true)] <===== true

那么这在 .NET 4.5 中是最简单的,通过新的CustomAttributeData API:

using System.ComponentModel;
using System.Reflection;

public static class Program

    static void Main()
    
        PropertyInfo prop = typeof(Foo).GetProperty("Bar");
        var val = GetPropertyAttributes(prop, "DisplayName");
    
    public static object GetPropertyAttributes(PropertyInfo prop, string attributeName)
    
        // look for an attribute that takes one constructor argument
        foreach(CustomAttributeData attribData in prop.GetCustomAttributesData()) 
        
            string typeName = attribData.Constructor.DeclaringType.Name;
            if(attribData.ConstructorArguments.Count == 1 &&
                (typeName == attributeName || typeName == attributeName + "Attribute"))
            
                return attribData.ConstructorArguments[0].Value;
            
        
        return null;
    


class Foo

    [DisplayName("abc")]
    public string Bar  get; set; 

【讨论】:

这行得通,但不是我所需要的。我根据您的代码用答案更新了我的问题。谢谢你得到了我需要的东西!【参考方案2】:

正如马克所说,属性没有值,本身。但是,您可以使用您为每个自定义属性实现的 Value 属性创建一个接口。然后你要做的就是验证 Attribute 实现了你的接口,然后获取 Value。

例子:

public static object GetPropertyAttributes(PropertyInfo prop, string attributeName)

    object[] attrs = prop.GetCustomAttributes(true);

    foreach (object attr in attrs)
    
        //THIS SHOULD BE REFLECTION
        if (attr is IMyCustomAttribute) // check if attr implements interface (you may have to reflect to get this)
        
            return (attr as IMyCustomAttribute).Value
        

    


// Your interface
public interface IMyCustomAttribute

    object Value  get; set; 


// Attribute implementing interface
public SomeCustomAttribute : Attribute, IMyCustomAttribute

    object Value  get; set; 

    // Other attribute code goes here

【讨论】:

这将使我处于了解接口类型的相同位置。虽然我可以在核心代码中创建接口来访问值... 本质上,知道一个类(在此可以自定义属性)有一个 Value 属性与声明一个具有 Value 属性的接口是一样的。如果您无法使用自定义属性实现接口,您仍然可以使用反射来查找名为 Value 的属性。 是的,我就是这么做的。感谢您的帮助。

以上是关于在不知道属性类型的情况下从属性和列表值中获取属性值的主要内容,如果未能解决你的问题,请参考以下文章

在不知道所有属性的情况下从 HTML 标记内部获取文本

在不更改属性顺序的情况下获取 XML

在不知道元素类型的情况下将项添加到列表中

Typeahead.js - 在多个属性值中搜索

如何从内联样式属性中获取值并将其放入最接近的输入值中? jQuery

我可以在不使用反射的情况下获取类中字段或属性的 PropertyInfo 吗?