-1

I have a lot of lists of different types, and a dictionary that stores for each type the according list. I would like to add an item to the list of its type:

    class Demo
    {
        [Serializable] class A{}
        [Serializable] class B{}
        [Serializable] class Z{}

        List<A> a = new List<A>();
        List<B> b = new List<B>();
        List<Z> z = new List<Z>();

        Dictionary<Type, object> dict;

        Demo()
        {
            dict = new Dictionary<Type, object>
            {
                {typeof(List<A>), a},
                {typeof(List<B>), b},
                {typeof(List<Z>), z},
            };
        }

        void Add(dynamic items)
        {
            var type = items.GetType();         
            dynamic list = dict[type];          
            list.AddRange( items );
        }
        
        

        static void Main()
        {
            var demo = new Demo();
            var json = JsonConvert.SerializeObject(new List<B>(){new B()});
            var type = typeof(List<B>);

            //compiler has no information of the type of item
            //the type used for deserialization is not known at compile time
            var item = JsonConvert.DeserializeObject(json, type );
            demo.Add(item);                     
        }
    }

This is working, but I wonder whether there is a solution without using the dynamic type - Is there a way to convert the entry in the dictionary to List<T>, or do you have another idea how to solve this problem dynamically without dynamic?

Please note that I cannot use

void Add<T>( T item ) {...}

Since the compile-time-type of the item is object, for instance from

object item = JsonConvert.DeserializeObject( json , item_type );
draz
  • 793
  • 6
  • 10
  • Can you post some code that compiles? It's a bit hard to follow what you're doing. For example, what's the underlying type of `items` when passed to `Add()`? You're converting `dict` to the type of `items` and then calling `AddRange()` on it, but `AddRange()` isn't a member of `Dictionary`, so how can you convert `dict` to something that has that member? – Matthew Watson Feb 14 '22 at 09:27
  • Does this answer your question? [How to deserialize a JObject to .NET object](https://stackoverflow.com/questions/4441466/how-to-deserialize-a-jobject-to-net-object) – funatparties Feb 14 '22 at 09:45
  • What would you do with the object once it is in the list? If you don't know the type, there isn't much you can do with that anyway, so you may as well just use `object`. If there is specific handling that needs to be done, but when you actually call it you don't need to know what it is, one options is: create a base `abstract` class or interface which supports the functionality you need, then derive from it a generic type `Derived : Base`. Then you can use reflection to create this object, and store it in a `List`. Now all functionality is available without knowing the actual type. – Charlieface Feb 14 '22 at 11:06
  • @MatthewWatson: sorry, I simplified the actual code too much - my bad – draz Feb 15 '22 at 07:41
  • @funatparties no, since I do not have the type information at compile time – draz Feb 15 '22 at 07:41
  • @Charlieface the list is typed, so the entries in the list behave like normal typed objects – draz Feb 15 '22 at 07:44
  • But what are you going to do with typed objects if you don't know the type at compile time? Do they have a common interface or base class? Or are you using reflection? – Charlieface Feb 15 '22 at 08:50
  • @Charlieface: within the list, the type is known even to the compiler, so once it is in the list, you can do whatever you want. I just try to bypass the dynamic keyword since I like strong typing – draz Feb 16 '22 at 08:23
  • @Charlieface: since the objects in the dictionary (a,b,z) are also available by simply access a,b and z directly, the compiler knows the type - a,b and z ARE of type List . So the compiler allows a[0].MyMethod() without using dynamic. – draz Feb 16 '22 at 15:01
  • Yes but you would need to cast the list itself, as it is stored in a `Dictionary`. You're still not telling us what you hope to *do* with these objects. Please give an actual example of what you are trying to achieve – Charlieface Feb 16 '22 at 15:06
  • the objects in the lists are data upserted from different sources and used from time to time for calculations, where I have to return somthing like a.Where( x => x.timestamp > threshold ). I do not need to cast the lists, since they are not only in the dict but also in the class. so I can access it by demo.a, demo.b etc. – draz Feb 16 '22 at 15:13

1 Answers1

0

use reflection:

void Add(object items)
{
    var type = items.GetType();
    var method = type.GetMethod("AddRange");
    var list = dict[type];                                              
    var ret = method.Invoke(list, new object[]{items} );
}   
draz
  • 793
  • 6
  • 10
  • this is a correct solution since it solves the problem without using `dynamic`. However, using a string with the name of the method looks even worse than `dynamic`. I keep looking for a more elegant solution - – draz Feb 16 '22 at 15:28