1

私は最近、プロパティ属性を利用しようとしています。次のコード (別のアセンブリ内) は、特定の属性を持つプロパティのみを名前で取得します。問題は、検索対象の属性が最初の属性である必要があることです。検索対象の属性の後に配置されていない限り、別の属性がプロパティに追加されると、コードが壊れます。

IList<PropertyInfo> listKeyProps = properties
    .Where(p => p.GetCustomAttributes(true).Length > 0)
    .Where(p => ((Attribute)p.GetCustomAttributes(true)[0])
        .GetType().Name == "SomeAttribute")
    .Select(p => p).ToList();

私はこの回答を見ましたが、オブジェクトが Assembly.GetEntryAssembly() にあり、typeof(SomeAttribute) を直接呼び出すことができないため、機能させることができませんでした。

これをどのように変更して、壊れにくくすることができますか?

[編集:] 別のアセンブリにあるにもかかわらず、属性の型を特定する方法を見つけました。

Assembly entryAssembly = Assembly.GetEntryAssembly();
Type[] types = entryAssembly.GetTypes();
string assemblyName = entryAssembly.GetName().Name;
string typeName = "SomeAttribute";
string typeNamespace
    = (from t in types
       where t.Name == typeName
       select t.Namespace).First();
string fullName = typeNamespace + "." + typeName + ", " + assemblyName;
Type attributeType = Type.GetType(fullName);

次に、dcastro によって以下に提案されているように、IsDefined() を使用することができました。

IList<PropertyInfo> listKeyProps = properties
    .Where(p => p.IsDefined(attributeType, true)).ToList();
4

1 に答える 1

2

では、プロパティのリストをフィルタリングして、特定の属性を宣言するものだけを取得しようとしていますか? コンパイル時に属性の型がわかっている場合は、そのブロック全体を次のように置き換えることができます。

Type attrType = typeof (SerializableAttribute);
properties.Where(p => p.IsDefined(attrType));

属性のタイプを名前で本当に識別する必要がある場合は、代わりにこれを使用します。

properties.Where(p => p.CustomAttributes.Any(
    attr => attr.AttributeType.Name == "SomeAttribute"));

編集

質問の 2 番目の部分への回答: あなたは物事を複雑にしすぎています。Typeアセンブリからオブジェクトを取得するために必要なのは、次のとおりです。

var attributeType = entryAssembly.GetTypes()
                                    .FirstOrDefault(t => t.Name == "SomeAttribute");

if (attributeType != null)
{
    //the assembly contains the type
}
else
{
    //type was not found
}

アセンブリ名、型名、名前空間を取得してからすべてを連結する必要はありません(読む:すべきではありません)。

Typeしかし、オブジェクトを取得する意味はありますか? 型を取得するためにまだ文字列を使用していますが、これは保守が難しく、壊れやすいものです。他の可能性について考えたことはありますか?

さらに質問がある場合は、別の質問として投稿してください。

于 2013-11-07T23:18:25.470 に答える