从不同的程序集中检索具有给定属性的属性

时间:2013-11-07 23:10:01

标签: c# .net linq reflection attributes

我最近一直试图利用属性属性。以下代码(在不同的程序集中)仅按名称检索具有特定属性的那些属性。问题是它要求搜索属性是第一个属性。如果向属性添加了不同的属性,代码将会中断,除非它被放置在搜索属性之后。

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();

我确实看过this answer,但由于对象在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);

然后我可以使用IsDefined(),如dcastro所提出的那样:

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

1 个答案:

答案 0 :(得分:2)

那么,您是要尝试过滤属性列表,只检索那些声明特定属性的人?如果在编译时知道属性的类型,则可以用以下内容替换整个块:

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

如果您确实需要按名称识别属性的类型,请改用:

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

修改

回复问题的第二部分: 你太复杂了。为了从程序集中获取Type对象,您只需要:

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

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

您不必(读取: 不)检索程序集名称,键入名称,命名空间,然后连接所有内容。

但检索Type对象有什么意义吗?您仍然使用字符串来检索难以维护且易于破坏的类型。您是否想过其他可能性?

如果您还有其他问题,请将其作为单独的问题发布。