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

然后我能够使用 IsDefined(),如下 dcastro 建议的那样:

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

编辑

回答你问题的第二部分:你把事情复杂化了。为了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 回答