How to sort through a generic list object

2019-09-19 10:23发布

My code is designed to parse an unknown json file using json.net that has nested classes and create checkboxes to easily look through it.

At some point during the parsing it arrives to a List object

I have the type and the actual object

The type has AssemblyQualifiedName "System.Collections.Generic.List`1[[Calibration.Camera, CalibrationOrganizer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

The object is a List<Calibration.Camera>

If I loop through the List this way it works, but the problem is I'm assuming a known data type, which I don't. This is just one of many data types in the json file

if (currentType.Name == "List`1")
{
    for (int i = 0; i < ((List<Calibration.Camera>)currentValue).Count; i++)
    {
        cbox = new CheckBox();
        cbox.Text = "[" + i.ToString() + "]";
        cbox.Name = prev_properties + "!" + curr_property;
        cbox.AutoSize = true;
        cbox.Location = new Point(1100 + prop_list.Count() * 100, i++ * 20); //vertical
        cbox.CheckedChanged += new EventHandler(ck_CheckedChanged);
        this.Controls.Add(cbox);
    }   
}

If I try this, it wont compile

for (int i = 0; i < currentValue.Count; i++) {...}

with error: Operator '<' cannot be applied to operands of type 'int' and 'method group'

If I try this, it crashes

for (int i = 0; i < ((List<object>)currentValue).Count; i++)

with exception: System.InvalidCastException: 'Unable to cast object of type 'System.Collections.Generic.List1[Calibration.Camera]' to type 'System.Collections.Generic.List1[System.Object]'.'

So Im not sure what I can do,

I can parse the AssemblyQualifiedName and get the Object type as a string, but how do I convert it to an object type again?

1条回答
爷的心禁止访问
2楼-- · 2019-09-19 10:59

It's a lot simpler if you cast it ahead of time. For example:

if (currentType.Name == "List`1")
{
    var list = currentValue as List<Calibration.Camera>;
    if (list == null) throw new ArgumentException("currentType and currentValue do not match.");
    foreach (var camera in list)
    {
        cbox = new CheckBox
        {
            Text = "[" + i.ToString() + "]",
            Name = prev_properties + "!" + curr_property,
            AutoSize = true,
            Location = new Point(1100 + prop_list.Count() * 100, i++ * 20) //vertical
        };
        cbox.CheckedChanged += new EventHandler(ck_CheckedChanged);
        this.Controls.Add(cbox);               
    }
}

In this example, we "cast" using as and do a null check to ensure it's the right type (you can throw an exception or just skip it silently if you prefer).

If you're not sure it's an actual List<Camera> but you know it's some kind of enumerable, you can cast to a non-generic IEnumerable (not IEnumerable<T>) and then use OfType<> on it. That will extract anything in the list that matches the type you want, and also cast it to a generic/typed IEnumerable<T>, which you can then use ToList() on.

if (currentType.Name == "List`1")
{
    var enumerable = currentValue as IEnumerable;
    if (enumerable == null) throw new ArgumentException("Doesn't seem to be a list.");
    var list = enumerable.OfType<Calibration.Camera>().ToList();
    foreach (var camera in list)
    {
        //etc....
查看更多
登录 后发表回答