简体   繁体   中英

How do I get DataContract attribute from PropertyInfo at the class level?

I have an extension method that I use attempt to extract some metadata from an object, such as this:

public static string ToTypeName(this object obj)
{
    string name;
    var asType = obj.GetType();
    if (Attribute.IsDefined(asType, typeof(DataMemberAttribute)) || Attribute.IsDefined(asType, typeof(DataContractAttribute)))
    {
        var attrName = obj.GetType().GetCustomAttributes(typeof(DataContractAttribute), true).SingleOrDefault() as DataContractAttribute;
        name = string.IsNullOrEmpty(attrName.Name) ? asType.Name : attrName.Name;
    }
    else
    {
        name = asType.Name;
    }
    return name;
}

I'm currently using it to scrap metadata from objects that are decorated with various attributes. In this example, it is looking for the DataContractAttribute and then pulling the value from the Name property. This works fine.

However, there are times when that object is of the PropertyInfo type. What is happening is that the Attribute.IsDefined is testing true, thus entering the block to be scraped, however, it is failing to cast so attrName is coming out null.

I added this block before the previous block:

if (obj is PropertyInfo)
{
    var asPropInfo = obj as PropertyInfo;
    if (Attribute.IsDefined(asPropInfo, typeof(DataMemberAttribute)) || Attribute.IsDefined(asPropInfo, typeof(DataContractAttribute)))
    {
        var attrName = asPropInfo.GetType().GetCustomAttributes(typeof(Attribute), true).SingleOrDefault();
        if (attrName is DataMemberAttribute)
        {
            var attr = attrName as DataMemberAttribute;
            name = string.IsNullOrEmpty(attr.Name) ? asType.Name : attr.Name;
        }
        else if (attrName is DataContractAttribute)
        {
            var attr = attrName as DataContractAttribute;
            name = string.IsNullOrEmpty(attr.Name) ? asType.Name : attr.Name;
        }
    }
}

the IsDefined check is still testing true, but still failing to cast. I looked at the CustomAttributes property of obj (as it enters the method) via watch variables and it shows 1 attribute of type DataContractAttribute , however, by the time i get to asPropInfo.GetType(), it has changed to Serializable .

It could be that i've been at this for too long and I'm not thinking clear, but does anyone have any input?

UPDATE: I was able to remove the GetType() and just call GetCustomAttributes() directly, however, the result is still not what I need. Here's what appears to be happening:

Imagine a Person class contains a member of type Person like so:

[DataContract(Name = "Employee")]
public class PersonDto{
    public string FirstName {get;set;}
    public string LastName {get;set;}

    [DataMember(Name = "Boss")]
    public Person Supervisor {get;set;}
}

What is happening during the scrape is that Supervisor is getting passed in as PropertyInfo along with it's DataMember attribute, and my extension is reading it and returning "Boss," and this totally makes sense. However, what I actually need at this stage is the DataContract attribute and here's why:

When the Supervisor property gets serialized, it will serialize as "Boss" and I need to know that, so I save that to a DTO. However, I also need to know that "Boss" is of the serialized "type" which is "Employee". This might seem weird, but makes sense in the end lol. I'm using this to help generate help documentation for our API. Internally, the class type might be "PersonDto", but the type that is displayed to the client is "Employee". So in terms of help documentation, the developer knows that there's a "Boss" element, but they also need to know that it is simply an instance of "Employee" (as far as they're concerned), so that they can look up documentation for that object. Does that makes sense?

I believe you don't need to call GetType on asPropInfo. Try that:

var attrName = asPropInfo.GetCustomAttributes(typeof(Attribute), true).SingleOrDefault();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM