我将一个属性网格绑定到一堆由其他开发人员编写的自定义对象。这些对象不断地被更改和更新,因此它们包含仅抛出NotImplemented Exceptions的属性。有时它们包括诸如
[过时(“用thingy代替获取其他东西”,true)]
而不是惹恼其他开发人员。我知道以后会改变的事情。我可以做些什么来确保我的属性网格不会在这些特定属性上中断?
谢谢您的帮助。其他开发人员对此表示赞赏;)
我将一个属性网格绑定到一堆由其他开发人员编写的自定义对象。这些对象不断地被更改和更新,因此它们包含仅抛出NotImplemented Exceptions的属性。有时它们包括诸如
[过时(“用thingy代替获取其他东西”,true)]
而不是惹恼其他开发人员。我知道以后会改变的事情。我可以做些什么来确保我的属性网格不会在这些特定属性上中断?
谢谢您的帮助。其他开发人员对此表示赞赏;)
我想您正试图在运行时将 PropertyGrid 绑定到对象,而不是在设计器中。如果你指的是winform设计器中的propertygrid,答案会不一样,你应该看看ControlDesigner的postFilterEvents方法。
最简单的解决方案是将要隐藏的属性的 BrowsableAttribute 设置为 false。这意味着当其他开发人员添加 ObsoleteAttribute 时,他们也应该添加[Browsable(false)]
。但我知道您想要更“自动”的东西。您可以编写一个方法来更改对象属性的可浏览属性,然后再将其传递给 PropertyGrid。这可以通过获取每个属性的 TypeDescriptor,然后获取其 BrowsableAttribute,并根据存在 ObsoleteAttribute 或抛出异常的事实来设置其值(这必须通过反射来完成,因为 browsable 是私有的) . 代码可能是这样的:
private static void FilterProperties(object objToEdit)
{
Type t = objToEdit.GetType();
PropertyInfo[] props = t.GetProperties();
// create fooObj in order to have another instance to test for NotImplemented exceptions
// (I do not know whether your getters could have side effects that you prefer to avoid)
object fooObj = Activator.CreateInstance(t);
foreach (PropertyInfo pi in props)
{
bool filter = false;
object[] atts = pi.GetCustomAttributes(typeof(ObsoleteAttribute), true);
if (atts.Length > 0)
filter = true;
else
{
try
{
object tmp = pi.GetValue(fooObj, null);
}
catch
{
filter = true;
}
}
PropertyDescriptor pd = TypeDescriptor.GetProperties(t)[pi.Name];
BrowsableAttribute bAtt = (BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)];
FieldInfo fi = bAtt.GetType().GetField("browsable",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
fi.SetValue(bAtt, !filter);
}
}
这应该有效,但它有一个限制。您正在编辑的类中必须至少有一个 BrowsableAttribute(设置为 true 或 false 都没有关系),否则 PropertyGrid 将始终为空。