I wanted to read all the public property values of objects and wrote following code:
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;
}
And call it like this:
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);
}
}
The Exception looks like this
System.InvalidOperationException: Timeouts are not supported on this stream. at System.IO.Stream.get_ReadTimeout()
Now I would like to exclude such unsupported Properties from the return value of GetListOfProperties
Your code by itself looks OK to me.
But I suspect that your approach has one fundamental design flaw: namely your assumption that you can read any property successfully, anytime, in any order.
Well-designed types might fulfill this assumption, but unfortunately there are types out there that follow different protocols:
An object may have a property HasValue
, which specifies whether another propery Value
may be queried (or whether that would result in an InvalidOperationException
or similar).
(A better-designed type might have a TryGetValue
method or a nullable Value
property instead.)
An object may have to be Initialize
-d first before anything can be done with it.
etc. You came across another such example with Stream.ReadTimeout
, which apparently simply isn't supported on MemoryStream
.
If you have to get your reflection code to work with any type, here are some options:
The easiest way is to simply "ignore" any errors by wrapping the call to propertyInfo.GetValue
in a try
/ catch
block (and perhaps collect all caught exceptions into an AggregateException
).
If you want to treat some specific types differently to work around particular issues (like your case with MemoryStream
), you could create various implementations of your reflection code and choose a strategy based on an object's Type
. Here's a very crude example to give you an idea:
interface IPropertyInspector { PropertyInfo[] GetProperties(object obj); } class GenericPropertyInspector : IPropertyInspector { /* your current implementation */ } class StreamPropertyInspector : IPropertyInspector { /* does not return eg 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
Such an additional level of indirection would allow you to filter out properties that are known to cause problems.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.