3

次のように、オブジェクトからいくつかのメタデータを抽出するために使用する拡張メソッドがあります。

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;
}

現在、さまざまな属性で装飾されたオブジェクトからメタデータをスクラップするために使用しています。DataContractAttributeこの例では、 Name プロパティから値を探して取得しています。これはうまくいきます。

ただし、そのオブジェクトが型の場合もありますPropertyInfo。何が起こっているかというと、Attribute.IsDefinedテストが true であるため、スクレイピングするブロックに入りますが、キャストに失敗しているため、attrNamenull が出てきます。

前のブロックの前にこのブロックを追加しました。

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;
        }
    }
}

IsDefinedチェックはまだ true をテストしていますが、まだキャストに失敗しています。ウォッチ変数を介して (メソッドに入ると)のCustomAttributesプロパティを調べたところ、 type の属性が 1 つ表示されていましたが、asPropInfo.GetType() に到達するまでに に変更されました。objDataContractAttributeSerializable

私はこれにあまりにも長い間携わっていて、明確に考えていない可能性がありますが、誰か意見がありますか?

更新: を削除して直接GetType()呼び出すことができましたGetCustomAttributes()が、結果はまだ必要なものではありません。何が起こっているように見えるかは次のとおりです。

Person クラスに次のような Person 型のメンバーが含まれているとします。

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

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

スクレイプ中に起こっていることは、その属性Supervisorとともに PropertyInfo として渡されDataMember、私の拡張機能がそれを読み取って「Boss」を返していることです。これは完全に理にかなっています。ただし、この段階で実際に必要なのはDataContract属性であり、その理由は次のとおりです。

Supervisorプロパティがシリアル化されると、「Boss」としてシリアル化され、それを知る必要があるため、それを DTO に保存します。ただし、「ボス」はシリアル化された「タイプ」である「従業員」であることも知っておく必要があります。これは奇妙に思えるかもしれませんが、最終的には理にかなっています笑。これを使用して、API のヘルプ ドキュメントを生成しています。内部的には、クラス タイプは "PersonDto" かもしれませんが、クライアントに表示されるタイプは "Employee" です。したがって、ヘルプ ドキュメントに関しては、開発者は「Boss」要素があることを知っていますが、それが単なる「Employee」のインスタンスであることも知っている必要があります (彼らに関する限り)。そのオブジェクトのドキュメント。それは理にかなっていますか?

4

1 に答える 1

2

asPropInfo で GetType を呼び出す必要はないと思います。それを試してください:

var attrName = asPropInfo.GetCustomAttributes(typeof(Attribute), true).SingleOrDefault();
于 2013-05-02T01:39:51.100 に答える