【问题标题】:Casting an object as an ObservableCollection<object>将对象转换为 ObservableCollection<object>
【发布时间】:2016-06-09 18:59:08
【问题描述】:

我正在尝试编写一个方法来获取 viewModel 中的所有 ObservableCollections 并将每个都转换为 ObservableCollection&lt;object&gt;。使用反射我已经能够将每个ObservableCollection&lt;T&gt; 作为一个对象,但是我很难将此对象转换为ObservableCollection&lt;object&gt;。到目前为止,这是我的代码:

var props = viewModel.GetType().GetProperties();

Type t = viewModel.GetType();

foreach (var prop in props)
{
    if (prop.PropertyType.Name == "ObservableCollection`1")
    {
        Type type = prop.PropertyType;
        var property = (t.GetProperty(prop.Name)).GetValue(viewModel);

        // cast property as an ObservableCollection<object>
    }
}

有人知道我应该怎么做吗?

【问题讨论】:

  • 转换为ObservableCollection&lt;object&gt; 不是类型安全的。你为什么要这样做?也许还有另一种方法可以实现您的目标。
  • 此线程中每个答案的主要缺点是,如果旧集合发生更改,新集合将不会更改或发送任何通知。如果不编写大量解决方法代码,就无法克服这个问题。有时这种限制或 CLR 类型系统真的很烦人。

标签: c# .net observablecollection


【解决方案1】:

将类型名称与字符串进行比较是个坏主意。为了断言它是ObservableCollection,您可以使用以下内容:

if (prop.PropertyType.IsGenericType && 
    prop.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))

可以这样提取和转换值:

foreach (var prop in viewModel.GetType().GetProperties())
{    
    if (prop.PropertyType.IsGenericType && 
        prop.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
    {
        var values = (IEnumerable)prop.GetValue(viewModel);

        // cast property as an ObservableCollection<object>
        var collection = new ObservableCollection<object>(values.OfType<object>());
    }
}

如果您希望将它们合并为一个集合,您可以这样做:

var values = viewModel.GetType().GetProperties()
    .Where(p => p.PropertyType.IsGenericType)
    .Where(p => p.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
    .Select(p => (IEnumerable)p.GetValue(viewModel))
    .SelectMany(e => e.OfType<object>());
var collection = new ObservableCollection<object>(values);

【讨论】:

    【解决方案2】:

    这个问题的答案在这里: https://stackoverflow.com/a/1198760/3179310

    但是为了说明你的情况:

    if (prop.PropertyType.Name == "ObservableCollection`1")
    {
        Type type = prop.PropertyType;
        var property = (t.GetProperty(prop.Name)).GetValue(viewModel);
    
        // cast property as an ObservableCollection<object>
        var col = new ObservalbeCollection<object>(property);
        // if the example above fails you need to cast the property
        // from 'object' to an ObservableCollection<T> and then execute the code above
        // to make it clear:
        var mecol = new ObservableCollection<object>();
        ICollection obscol = (ICollection)property;
        for(int i = 0; i < obscol.Count; i++)
        {
            mecol.Add((object)obscol[i]);
        }    
        // the example above can throw some exceptions but it should work in most cases
    }
    

    【讨论】:

    • 感谢您的建议。第一种方法会产生错误cannot convert from 'object' to 'System.Collections.Generic.List&lt;object&gt;',但第二种方法工作得很好。
    【解决方案3】:

    您可以使用Cast&lt;T&gt;() 扩展方法,但不要忘记,使用此方法(如下)将创建一个新实例,因此原始事件不起作用。如果你仍然想接收事件,你应该在它周围创建一个包装器。

    var prop = viewModel.GetType("ObservableCollection`1");
    
    var type = prop.PropertyType;
    var propertyValue = (t.GetProperty(prop.Name)).GetValue(viewModel);
    
    // cast property as an ObservableCollection<object>
    var myCollection = new ObservableCollection<object>(
                       ((ICollection)propertyValue).Cast<object>());
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 2017-07-04
      • 2012-10-21
      • 2021-09-27
      • 1970-01-01
      • 2022-11-01
      • 2011-11-27
      相关资源
      最近更新 更多