我想传递属性名称并返回值。这将是一个通用的util,它不会知道属性类型。
更新 如果有人需要这样做,这是实际的工作代码。我需要一种方法让核心代码解析属性而不知道它们是什么。
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;
}
答案 0 :(得分:7)
如果您的意思是“给定一个带有一个参数的属性,请给我这个值”,例如:
[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; }
}
答案 1 :(得分:0)
正如马克所说,属性没有值,本身。但是,您可以使用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
}