次のように、オブジェクトからいくつかのメタデータを抽出するために使用する拡張メソッドがあります。
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 であるため、スクレイピングするブロックに入りますが、キャストに失敗しているため、attrName
null が出てきます。
前のブロックの前にこのブロックを追加しました。
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() に到達するまでに に変更されました。obj
DataContractAttribute
Serializable
私はこれにあまりにも長い間携わっていて、明確に考えていない可能性がありますが、誰か意見がありますか?
更新: を削除して直接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」のインスタンスであることも知っている必要があります (彼らに関する限り)。そのオブジェクトのドキュメント。それは理にかなっていますか?