Mikhail Tulubaev
Mikhail Tulubaev

Reputation: 4271

How can I retrieve data from DisplayAttribute of interface?

I have the following code:

public interface TestInterface
{
    [Display(Name = "Test Property")]
    int Property { get; }
}

class TestClass : TestAttribute
{
    public int Property { get; set; }
}

Note, that the property of interface is marked with DisplayAttribute. When I am trying to get the value from attribute, the following code samples does not works.

First sample: direct access to property of class.

var t = new TestClass();

var a = t.GetType().GetProperty("Property").GetCustomAttributes(true);

Second sample: cast object to interface and get access to property.

var t = (TestInterface)new TestClass();

var a = t.GetType().GetProperty("Property").GetCustomAttributes(true);

But when I am passing object as a model for mvc view and calling @Html.DisplayNameFor(x => x.Property) it returns the correct string "Test Property".

View

@model WebApplication1.Models.TestInterface
...
@Html.DisplayNameFor(x => x.Property)

renders as

Test Property

How can I achieve the same result with code on server side? And why I can not do it with simple reflection?

Upvotes: 0

Views: 811

Answers (3)

Ebraheem
Ebraheem

Reputation: 703

You can try this one

 var t = new TestClass();
 var a = t.GetType().GetInterface("TestInterface").GetProperty("Property").GetCustomAttributes(true);

Upvotes: 1

hbulens
hbulens

Reputation: 1969

I have done something similar for the Description attribute. You could refactor this code (or better, make more generic) so it works for the Display attribute as well and not only for enums:

public enum LogCategories
{
    [Description("Audit Description")]
    Audit,
}


public static class DescriptionExtensions
{
    public static string GetDescription<T, TType>(this T enumerationValue, TType attribute)
        where T : struct
        where TType : DescriptionAttribute
    {
        Type type = enumerationValue.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
        }

        //Tries to find a DescriptionAttribute for a potential friendly name
        //for the enum
        MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
        if (memberInfo != null && memberInfo.Length > 0)
        {
            object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attribute is DescriptionAttribute)
            {
                if (attrs != null && attrs.Length > 0)
                {
                    return ((DescriptionAttribute)attrs[0]).Description;
                }
            }
            else
            {                   
            }                
        }
        //If we have no description attribute, just return the ToString of the enum
        return enumerationValue.ToString();
    }
}

As you see, the code uses some reflection to detect any attributes marked on the member (in my case the DescriptionAttribute but it could be the DisplayAttribute too) and returns the Description property to the caller.

Usage:

string auditDescription = LogCategories.Audit.GetDescription(); // Output: "Audit Description"

Upvotes: 0

grek40
grek40

Reputation: 13458

You can explicitely query the associated interface types for annotations:

var interfaceAttributes = t.GetType()
    .GetInterfaces()
    .Select(x => x.GetProperty("Property"))
    .Where(x => x != null) // avoid exception with multiple interfaces
    .SelectMany(x => x.GetCustomAttributes(true))
    .ToList();

The result list interfaceAttributes will contain the DisplayAttribute.

Upvotes: 1

Related Questions