目标类型MemoryStream

时间:2015-10-11 14:53:34

标签: c# reflection properties

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

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

的返回值中排除这些不受支持的属性

1 个答案:

答案 0 :(得分:3)

您的代码本身对我来说没问题。

但我怀疑你的方法有一个基本的设计缺陷:即你假设你可以随时以任何顺序成功阅读任何财产。

设计良好的类型可能会满足这一假设,但不幸的是,有些类型遵循不同的协议:

  • 一个对象可能有一个属性HasValue,它指定是否可以查询另一个属性Value(或者是否会导致InvalidOperationException或类似)。

    (设计得更好的类型可能会使用TryGetValue方法或可以为空的Value属性。)

  • 对象可能必须先Initialize - d才能完成任何操作。

等。您使用Stream.ReadTimeout遇到了另一个此类示例,MemoryStream显然不支持此示例。

如果您必须让您的反射代码与任何类型一起使用,以下是一些选项:

  1. 最简单的方法是通过在propertyInfo.GetValue / try块中包含对catch的调用来简单地“忽略”任何错误(并且可能会将所有捕获的异常收集到AggregateException)。

  2. 如果您想以不同方式处理某些特定类型以解决特定问题(例如MemoryStream的情况),您可以创建反射代码的各种实现,并根据对象{选择策略{ {1}}。这是一个非常粗略的例子,可以给你一个想法:

    Type

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