TargetInvocationException @ PropertyInfo.GetValue(target, null) 目标类型为 MemoryStream
TargetInvocationException @ PropertyInfo.GetValue(target, null) with Target Type MemoryStream
我想读取对象的所有 public 属性 值并编写了以下代码:
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);
}
}
异常看起来像这样
System.InvalidOperationException: Timeouts are not supported on this stream. at
System.IO.Stream.get_ReadTimeout()
现在我想从 GetListOfProperties
的 return 值中排除此类不受支持的属性
我觉得你的代码本身没问题。
但我怀疑您的方法存在一个基本的设计缺陷:即您假设您可以随时随地以任何顺序成功阅读任何 属性。
设计良好的类型可能会满足这个假设,但不幸的是,有些类型遵循不同的协议:
一个对象可能有一个属性HasValue
,指定是否可以查询另一个属性Value
(或者这是否会导致InvalidOperationException
或类似的)。
(设计更好的类型可能有 TryGetValue
方法或可为空的 Value
属性。)
一个对象可能必须先 Initialize
-d 才能对其进行任何操作。
等您在 Stream.ReadTimeout
中遇到了另一个这样的例子,显然 MemoryStream
.
不支持它
如果您必须让反射代码与 任何 类型一起使用,这里有一些选项:
最简单的方法是通过将对 propertyInfo.GetValue
的调用包装在 try
/catch
块中来简单 "ignore" 任何错误(也许将所有捕获的异常收集到 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
这种额外的间接级别将允许您过滤掉已知会导致问题的属性。
我想读取对象的所有 public 属性 值并编写了以下代码:
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);
}
}
异常看起来像这样
System.InvalidOperationException: Timeouts are not supported on this stream. at System.IO.Stream.get_ReadTimeout()
现在我想从 GetListOfProperties
我觉得你的代码本身没问题。
但我怀疑您的方法存在一个基本的设计缺陷:即您假设您可以随时随地以任何顺序成功阅读任何 属性。
设计良好的类型可能会满足这个假设,但不幸的是,有些类型遵循不同的协议:
一个对象可能有一个属性
HasValue
,指定是否可以查询另一个属性Value
(或者这是否会导致InvalidOperationException
或类似的)。(设计更好的类型可能有
TryGetValue
方法或可为空的Value
属性。)一个对象可能必须先
Initialize
-d 才能对其进行任何操作。
等您在 Stream.ReadTimeout
中遇到了另一个这样的例子,显然 MemoryStream
.
如果您必须让反射代码与 任何 类型一起使用,这里有一些选项:
最简单的方法是通过将对
propertyInfo.GetValue
的调用包装在try
/catch
块中来简单 "ignore" 任何错误(也许将所有捕获的异常收集到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
这种额外的间接级别将允许您过滤掉已知会导致问题的属性。