1

I want to write an extension method to get the value of the MaximumLength property on the StringLength attribute.

For example, I have a class:

public class Person
{
    [StringLength(MaximumLength=1000)]
    public string Name { get; set; }
}

I want to be able to do this:

Person person = new Person();
int maxLength = person.Name.GetMaxLength();

Would this be possible using some sort of reflection?

Andrew
  • 11,068
  • 17
  • 52
  • 62
  • 3
    I imagine you might be able to do something with a LINQ expressions with usage like: `int maxLength = StringLength.Get(() => person.Name);` EDIT: Here's a basic concept of what I'm talking about; different usage, but the idea is to pass a lambda expression in and leverage the LINQ `Expression` object to inspect the referenced property and retrieve its attributes: http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression – Chris Sinclair Jul 10 '13 at 01:20

2 Answers2

5

If you use LINQ expressions, you can pull out the information via reflection with slightly different syntax (and you get to avoid defining an extension method on a commonly used string type):

public class StringLength : Attribute
{
    public int MaximumLength;

    public static int Get<TProperty>(Expression<Func<TProperty>> propertyLambda)
    {
        MemberExpression member = propertyLambda.Body as MemberExpression;
        if (member == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a method, not a property.",
                propertyLambda.ToString()));

        PropertyInfo propInfo = member.Member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.",
                propertyLambda.ToString()));

        var stringLengthAttributes = propInfo.GetCustomAttributes(typeof(StringLength), true);
        if (stringLengthAttributes.Length > 0)
            return ((StringLength)stringLengthAttributes[0]).MaximumLength;

        return -1;
    }
}

So your Person class might be:

public class Person
{
    [StringLength(MaximumLength=1000)]
    public string Name { get; set; }

    public string OtherName { get; set; }
}

Your usage might look like:

Person person = new Person();

int maxLength = StringLength.Get(() => person.Name);
Console.WriteLine(maxLength); //1000

maxLength = StringLength.Get(() => person.OtherName);
Console.WriteLine(maxLength); //-1

You can return something other than -1 for a property that didn't have that attribute defined. You weren't specific, but that's easy to change.

Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
  • Thanks mate - I think this is a good way to do it. Too bad I can't use extension methods, but oh well. – Andrew Jul 11 '13 at 04:08
1

This may not be the nicest way to do this, but if you dont mind suppling the property name you need to get the Attribute value for you could use something like

public static class StringExtensions
{
    public static int GetMaxLength<T>(this T obj, string propertyName) where T : class
    {
        if (obj != null)
        {
            var attrib = (StringLengthAttribute)obj.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance)
                    .GetCustomAttribute(typeof(StringLengthAttribute), false);
            if (attrib != null)
            {
                return attrib.MaximumLength;
            }
        }
        return -1;
    }
}

Usage:

Person person = new Person();
int maxLength = person.GetMaxLength("Name");

Otherwise using a function like Chris Sinclair mentioned in his comment would work nicely

sa_ddam213
  • 42,848
  • 7
  • 101
  • 110