2

Im trying to write a small framework for REST-API testing. Im using a lot of reflection and came to a problem I cant help myself.

Im using this line to extract a variable the user gives my as a path (string)

object o = input.GetType().GetProperty(name).propertyInfo.GetValue(input, null);

This object can be a normal type T or a List<T>. Now if its a List and I know the type everything is simple, I can use

List<string> l = (List<string>)o; // I know its a List<string> because the user told me

To parse the object into the given array. But I dont always know the type of the objects in the list and

List<object> l = (List<object>)o; // I dont know the type and I dont care

gives me an error.

Object of type "System.Collection.GenericList[System.String]" can not be converted to "System.Collection.GenericList[System.Object]"

Is there anything I can do to receive the list of objects? I dont want the user to specify the type because its only the last variable I want to care about. Like

The user wants to test "object1.a.b.c" I only need to know the type of c, because thats where the test runs.

TIA

9
  • 4
    is there a particular reason you're using reflection over, say, dynamic? Ed: you mention specifically that you "don't know... don't care" about the type, hence why I ask about dynamic Commented Jun 25, 2019 at 14:42
  • Can't you do all this at the JSON level with JObjects and JTokens? Commented Jun 25, 2019 at 14:53
  • stackoverflow.com/questions/56388145/… Commented Jun 25, 2019 at 15:12
  • @JoshE I use reflection mainly because I want the user to give me the "path" to the variable as a string, which allows me to put some extra syntax in like base.arr[x].i Commented Jun 25, 2019 at 16:04
  • @AvinKavish JSON level would be plan B. The main reason for not using JSON level is, because I want it to be "type-safe" and thus allow the user to use member-functions on the given variable he wants to test. Like test<myClass>("a.b.c", x => x.foo() > 5); // c is of type myClass Commented Jun 25, 2019 at 16:05

2 Answers 2

7

You may convert it to IEnumerable<object>, but not List<object>. The reason is: a list of bananas is not a list of fruit because you can put an apple into a list of fruit, but not into a list of bananas. Since the two types allow different operations, they are not compatible.

A sequence has no "put into" operation, so it is possible to use a list of bananas as a sequence of fruit. Similarly, you can use a list of strings as a sequence of objects, but not a list of objects.

This feature is called generic covariance; for more information, do a search on C# covariance and you'll find plenty of articles explaining how it works.

Note in particular that covariance only works on reference types; you may not use a sequence of integers as a sequence of objects. Do you see why?

Alternatively, if you have an IEnumerable in hand, you can make a copy of any sequence into a list of objects with mysequence.Cast<object>().ToList(). But this is a copy, not a reference conversion.

Sign up to request clarification or add additional context in comments.

6 Comments

Does the "special" case of String/string have special behavior in this regard due to their value type/reference type duality?
@JoshE: I have no idea what you're talking about. Can you explain in more detail? I suspect you have a very wrong belief about reference types, and we should dispel that wrong belief.
sorry for the ambiguity; I know that covariance applies to strings the same way it would apply to any other reference type, ~~. ed: I am a bit rusty on string/value type mechanics -immutability != value type
@JoshE: Under what circumstances can "strings be treated as value types"? Strings are compared by value because they override Equals; is that what you're thinking of?
@JoshE: Got it. Covariance does not affect equality comparisons, nor is it affected by them. (Though, interestingly, IComparable<T> is contravariant which is sometimes useful.)
|
1

Since your problem begins at processing dynamic objects that arrive as JSON to the server, it's quite convenient to use the JSON Processing library itself to test for certain characteristics before converting to POCOs. Using newtonsoft's JSON.Net,

var o = JObject.Parse(json);
JToken property = o["a"]["b"]["c"];
if (property != null)
{
    if (property.Type == JTokenType.Array)
    {
      // Process property as array

    }
    else if  (property.Type == JTokenType.Object)
    {
      // Process property as object
    }
    // Magnitude of other types
}

I do understand the need to convert to .NET types before final processing but I would highly recommend beginning with JObjects as the library is designed for this purpose and provides numerous convenience methods for many dynamic operations that C# doesn't provide natively.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.