Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast a object to IList<T> with unknown type T


I have a object[] containig some values. I want to extract infomation out of it, but I fail at casting the second object in the array (a WeakReference) to a IList with T as the third value in the array.

Take a look at my code:

object[] vals = GetValues(); //vals[2] = WeakReference, vals[3] = Type of T, vals[4] = index in the list
IList<((Type)vals[3])> list = (IList<((Type)vals[3])>)(((WeakReference)vals[2]).Target); //This line does not even compile, seems like I'm doing something wrong..
object oo = list.ElementAt((int)vals[4]);
//Do something with oo...

Any suggestions how I can cast the Target of the WeakReference to a IList interface with T = vals[3] ?

like image 475
alex Avatar asked Dec 27 '22 21:12

alex


2 Answers

It's really strange that you are packing so much heterogeneous information into an array. Arrays are normally used to store elements of the same type. Why not encapsulate the data in a proper type?

But to answer the question as asked - in C# 4, you can use dynamic:

var target = ((dynamic)vals[2]).Target;

if(target != null)
{
    object oo = Enumerable.ElementAt(target, vals[4]);
    //Do something with oo...
}

(EDIT: If you want to minimize the use of dynamic here, cast to a WeakReference and leave the dynamic call to the end. This way, type-safety is 'maximized'.)

Otherwise, you can use reflection:

object target = ((WeakReference)vals[2]).Target;

if (target != null)
{
    object oo = target.GetType()
                      .GetProperty("Item")
                      .GetValue(target, new[] { vals[4] });
    //Do something with oo...
}

(EDIT: If the indexer could be explicitly implemented, you'll probably need to use the interface mappings.)

like image 86
Ani Avatar answered Jan 13 '23 04:01

Ani


It was already suggested that you could use dynamic, but it sounds like you are also supposed to check that the object has the specified type. I’ve also kept use of dynamic to a minimum:

object target = ((WeakReference) vals[2]).Target;

if (target == null)
    throw new InvalidOperationException("Target cannot be null.");

object result = Enumerable.ElementAt((dynamic) target, (int) vals[4]);

if (result != null && !((Type) vals[3]).IsAssignableFrom(result.GetType()))
    throw new InvalidOperationException(string.Format("The retrieved object is a {0}, but the expected type was {1}.", result.GetType(), (Type) vals[3]));

return result;
like image 30
Timwi Avatar answered Jan 13 '23 06:01

Timwi