TargetInvocationException @ PropertyInfo.GetValue(target, nu



我想读取对象的所有公共属性值,并编写了以下代码:

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显然不支持它。

如果你必须让你的反射代码与任何类型一起工作,这里有一些选项:

  1. 最简单的方法是通过在try/catch块中包装对propertyInfo.GetValue的调用来简单地"忽略"任何错误(也许将所有捕获的异常收集到AggregateException中)。

  2. 如果您想以不同的方式对待某些特定类型以解决特定问题(例如您使用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
    

    这种额外的间接级别将允许您过滤掉已知会导致问题的属性。

相关内容

  • 没有找到相关文章

最新更新