我想读取对象的所有公共属性值,并编写以下代码:
private List<PropertyInfo> GetListOfProperties(object objectToRegister,
BindingFlags bindingFlags = BindingFlags.Instance |
BindingFlags.Public)
{
Type type = objectToRegister.GetType();
List<PropertyInfo> curListOfProperties = new List<PropertyInfo>();
curListOfProperties.AddRange(type.GetProperties()
.Where((propertyInfo) =>
!propertyInfo.GetIndexParameters().Any()));
return curListOfProperties;
}
并称之为:
var objectToRegister = new MemoryStream();
// ... eventually write things into MemoryStream e.g. Image.Save(objectToRegister , "Bmp")
// ... eventually do nothing with objectToRegister
foreach (var propertyInfo in GetListOfProperties(objectToRegister))
{
if (propertyInfo.CanRead)
{
// -->> TargetInvocationException
value = propertyInfo.GetValue(objectToRegister , null);
}
}
Exception看起来像这样
System.InvalidOperationException:此流不支持超时。在 System.IO.Stream.get_ReadTimeout()
现在我想从GetListOfProperties
答案 0 :(得分:3)
您的代码本身对我来说没问题。
但我怀疑你的方法有一个基本的设计缺陷:即你假设你可以随时以任何顺序成功阅读任何财产。
设计良好的类型可能会满足这一假设,但不幸的是,有些类型遵循不同的协议:
一个对象可能有一个属性HasValue
,它指定是否可以查询另一个属性Value
(或者是否会导致InvalidOperationException
或类似)。
(设计得更好的类型可能会使用TryGetValue
方法或可以为空的Value
属性。)
对象可能必须先Initialize
- d才能完成任何操作。
等。您使用Stream.ReadTimeout
遇到了另一个此类示例,MemoryStream
显然不支持此示例。
如果您必须让您的反射代码与任何类型一起使用,以下是一些选项:
最简单的方法是通过在propertyInfo.GetValue
/ try
块中包含对catch
的调用来简单地“忽略”任何错误(并且可能会将所有捕获的异常收集到AggregateException
)。
如果您想以不同方式处理某些特定类型以解决特定问题(例如MemoryStream
的情况),您可以创建反射代码的各种实现,并根据对象{选择策略{ {1}}。这是一个非常粗略的例子,可以给你一个想法:
Type
这种额外的间接级别将允许您过滤掉已知会导致问题的属性。