通用集合 - 检查类属性是否为1

时间:2010-11-02 22:09:37

标签: c# generics reflection

我对我正在编写的通用帮助程序类进行了简单的类型检查。如果你看一下源代码,这个想法就会很清楚。它适用于普通的东西,比如DateTime和bool,但我遇到了泛型问题。

如何查看例如ObservableCollection< 某事>并计算它。我不希望能够渲染所有东西(毕竟它是一个调试控件),但是如果有一个集合,我想知道它是否有元素。

尝试了一些变化,但都没有奏效。不能那么难,搜索词只是吮吸(通用,列表,收藏) - 所有不是很友好的谷歌: - )

[编辑]
好吧,我玩了一下,我靠近了。但是GetValue()函数存在一个奇怪的问题。如果你看一下示例类,一个字符串属性工作正常,构造函数中设置的那个显示“NULL” - 怎么会这样。哦,顺便问一下。我在Windows Phone 7中工作 - 但这应该不会影响这些基本的东西,是吗? [结束编辑]

我的功能的更新版本:

        private static FrameworkElement CreateContent(System.Reflection.PropertyInfo propertyInfo, object parent)
    {

        var propValue = propertyInfo.GetValue(parent, null);

        // NULL

        if (propValue == null) return new TextBlock() { Text = "NULL" };

        // Simple cases

        if (propertyInfo.PropertyType == typeof(int))
            return new TextBlock() { Text = propValue.ToString() };

        if (propertyInfo.PropertyType == typeof(DateTime))
            return new TextBlock() { Text = ((DateTime)propValue).ToShortTimeString() };

        if (propertyInfo.PropertyType == typeof(string))
            return new TextBlock() { Text = propValue.ToString() };

        // More exotic cases

        if (typeof(IList).IsAssignableFrom(propValue.GetType()))
                return new TextBlock() {Text = ((IList) propValue).Count.ToString()};

        if (typeof(ICollection).IsAssignableFrom(propValue.GetType()))
            return new TextBlock() { Text = ((ICollection)propValue).Count.ToString() };

        if (typeof(IEnumerable).IsAssignableFrom(propValue.GetType()))
            return new TextBlock() { Text = ((IEnumerable)propValue).Cast<object>().Count().ToString() };

        // If all fails, at least tell me the type

        return new TextBlock() {Text = propertyInfo.PropertyType.Name};
    }

非常奇怪的测试用例(查找StringPropertyA和B)

 public class DebugService : ServiceBase, IDebugService
{
    public DebugService(IUnityContainerPhone container) : base(container)
    {
        DateTimeProperty = DateTime.Now;
        StringEmptyProperty = "";
        StringObsColl = new ObservableCollection<string>() {"A", "B", "C"};
        StringList = new List<string>(){"X", "Y", "Z"};

        StringPropertyB = "Will not show up";

    }

    public override string Description
    {
        get { return "Does nothing, for debug purposes"; }
    }

    public DateTime DateTimeProperty { get; private set; }
    public int IntProperty { get { return 23; } }
    public string StringPropertyA { get {return  "Is OK";}  }
    public string StringPropertyB { get; private set; }
    public string StringEmptyProperty { get; private set; }
    public string StringNullProperty { get; private set; }
    public ObservableCollection<string> StringObsColl { get; private set; }
    public IList<string> StringList { get; private set; }
}

3 个答案:

答案 0 :(得分:1)

是否有必要走这条路?

if (parent is DateTime)
   return new TextBlock() { Text = ((DateTime)parent).ToShortTimeString() };

if (parent is ICollection)
   return new TextBlock() { Text = ((ICollection)parent).Count };

if (parent is IEnumerable)
   return new TextBlock() { Text = ((IEnumerable)parent).Count() }; //assumes System.Linq

...

return new TextBlock() { Text = parent.ToString() };

答案 1 :(得分:1)

propertyInfo.PropertyType.IsAssignableFrom(typeof(IList))

这是一个经典错误(我认为它因value is IList语法而很常见)。你真正想要的是:

typeof(IList).IsAssignableFrom(propertyInfo.PropertyType)

还有其他问题需要考虑,例如是否要支持其他类型的集合(并非所有集合都将实现IList。)如果您特别想要将值作为泛型集合访问,那么这是一个有用的提示是你可以使用typeof(IList<>)获取非专业泛型类型。

答案 2 :(得分:0)

我认为你的IsAssignable从方法调用了。我想你需要说typeof(IList).IsAssignableFrom(propertyInfo.PropertyType)

无论如何,我会直接检索对象并对其进行反思,而不是反映属性的类型。这样,如果你有一个object类型的属性,它返回一个列表,它将在你的调试控件中正确显示。

private static FrameworkElement CreateContent(System.Reflection.PropertyInfo propertyInfo, object parent)
{
    object propValue = propertyInfo.GetValue(parent, null);

    if (propValue is ICollection)
        return new TextBlock() { Text = ((ICollection)propValue).Count.ToString() };
    else if (propValue is ...)
        return new TextBlock() { Text = ... };
    else
        return new TextBlock() { Text = propValue.ToString() };
}