我最近一直试图利用属性属性。以下代码(在不同的程序集中)仅按名称检索具有特定属性的那些属性。问题是它要求搜索属性是第一个属性。如果向属性添加了不同的属性,代码将会中断,除非它被放置在搜索属性之后。
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();
答案 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
对象有什么意义吗?您仍然使用字符串来检索难以维护且易于破坏的类型。您是否想过其他可能性?
如果您还有其他问题,请将其作为单独的问题发布。