Search code examples
c#.netlinqgenericsodata

Loading data from different collection based on parameter


I'm using OData Connected Service to consume OData. In my endpoint, there are many collections, so in order to avoid spaghetti code I thought I would execute my code with a parameter which would tell, which collection to use.

Here's a code snippet of what I'm doing for single collection:

 var ctx = new ODataService(new Uri("http://urlofodataendpoint/OData/"));
            ctx.Credentials = System.Net.CredentialCache.DefaultCredentials; 
            ctx.Format.UseJson();

            var query = from f in ctx.Files
                        select new File
                        {
                            Title = f.Title
                        };
            DataServiceCollection<File> files = new DataServiceCollection<File>(query);

            while (files.Continuation != null)
                files.Load(ctx.Execute(files.Continuation));


            foreach (var f in files)
            {
                //do something for each File

            }

In this case, Files is collection of type of File. I would like to do this code for every collection. Of course, each collection has a different type in it. Here's what I tried:

string nameOfCollection = "Files";
            var ctx = new ODataService(new Uri("https://urlofodataendpoint/OData/"));
            ctx.Credentials = new System.Net.CredentialCache.DefaultCredentials; 
            ctx.Format.UseJson();


            dynamic type = ctx.Links;
            PropertyInfo[] PI = ctx.GetType().GetProperties();

            for(int i=0; i<PI.Count();i++)
            {
                if (PI[i].Name == nameOfCollection )
                    type = PI[i];
            }
            Console.WriteLine(type);

            //Type itemtype = type.GetType().GetGenericArguments().Single();

            var query = from f in ((IEnumerable<Type>)type).Cast<dynamic>()
                        select f;

            DataServiceCollection <dynamic> files = new DataServiceCollection<File>(query);

            while (files.Continuation != null)
                files.Load(ctx.Execute(files.Continuation));

Unfortunately the

var query = from f in ((IEnumerable<Type>)type).Cast<dynamic>()
                        select f;

part fails with

System.InvalidCastException: 'Unable to cast object of type 'System.Reflection.RuntimePropertyInfo' to type 'System.Collections.Generic.IEnumerable`1[System.Type]'.'

Also the part when I want to assign DataServiceCollection doesn't work:

Error CS1503 Argument 1: cannot convert from 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable'

How can I chose the collection dynamically and query it?


Solution

  • You got invalid cast when you try to convert variable type to IEnumerable<Type>.

    Consider change this code:

    var query = from f in ((IEnumerable<Type>)type).Cast<dynamic>()
                        select f;
    

    to:

    var query = from f in ((IEnumerable)type.GetValue(ctx)).Cast<dynamic>()
                        select f;