I want to pass in the attribute name and return the value. This will be in a generic util and it will not know the attribute type.
Update This is the actual working code if someone needs to do this. I needed a way to have the core code parse the attributes without knowing what they were.
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;
}
If you mean "given an attribute that takes one parameter, give me that value", for example:
then this is easiest in .NET 4.5, via the new
CustomAttributeData
API:As Mark said, Attributes don't have values, per se. You could, however, create an interface with with a Value property which you implement for each of your custom Attributes. Then all you have to do is verify that the Attribute implements you interface and then get the Value.
Example: