我想读取对象的所有公共属性值,并编写了以下代码:
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);
}
}
异常看起来像这样
系统。InvalidOperationException:此流不支持超时。在System.IO.Stream.get_ReadTimeout ()
现在我想从GetListOfProperties
你的代码本身看起来不错。
但是我怀疑你的方法有一个基本的设计缺陷:即你假设你可以在任何时间,以任何顺序成功读取任何属性。
设计良好的类型可能满足这个假设,但不幸的是,有一些类型遵循不同的协议:
一个对象可以有一个属性
HasValue
,它指定是否可以查询另一个属性Value
(或者是否会导致InvalidOperationException
或类似的结果)。(一个更好设计的类型可能有一个
TryGetValue
方法或一个可空的Value
属性代替)一个对象可能必须先被
Initialize
-d,然后才能对它做任何事情。
等。您遇到了Stream.ReadTimeout
的另一个这样的例子,MemoryStream
显然不支持它。
如果你必须让你的反射代码与任何类型一起工作,这里有一些选项:
最简单的方法是通过在
try
/catch
块中包装对propertyInfo.GetValue
的调用来简单地"忽略"任何错误(也许将所有捕获的异常收集到AggregateException
中)。如果您想以不同的方式对待某些特定类型以解决特定问题(例如您使用
MemoryStream
的情况),您可以创建反射代码的各种实现,并根据对象的Type
选择策略。下面是一个简单的例子:interface IPropertyInspector { PropertyInfo[] GetProperties(object obj); } class GenericPropertyInspector : IPropertyInspector { /* your current implementation */ } class StreamPropertyInspector : IPropertyInspector { /* does not return e.g. ReadTimeout if CanTimeout is false */ } Dictionary<Type, IPropertyInspector> inspectors = ...; inspectors[typeof(MemoryStream)] = new StreamPropertyInspector(); ... Type t = objectToRegister.GetType(); IPropertyInspector inspector; if (!inspectors.TryGetValue(t, out inspector)) { inspector = new GenericPropertyInspector(); } var properties = inspector.GetProperties(objectToRegister): // do something with properties
这种额外的间接级别将允许您过滤掉已知会导致问题的属性。