Search code examples
c#linqdefensive-programmingasqueryable

No Exists method so I want to use AsQueryable for defensive programming


I am writing some code which queries the Visual Studio object model.

I see that there is no Exists method on the Projects collection object but I do like defensive programming and not relying on try catch blocks. So I see there is AsQueryable() on the Projects object and I was wondering if this could help.

I can see here the sort of code I want to write,

IQueryable<Student> query = 
    objStudent.AsQueryable().Where(student => student.Name.Contains("Alavala"));

but for me it would be something like

IQueryable<EnvDTE.Project> query = 
    sol.Projects.AsQueryable().Where(proj => proj.Name=project);

but this does not compile giving the error message

'IQueryable' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'IQueryable' could be found (are you missing a using directive or an assembly reference?)

Is it just a missing reference? Here is the minimal recreatable code ...

using System.Linq;
using System.Runtime.InteropServices;

namespace AsQueryableConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            /* ensure the solution is running in a separate instance of Visual Studio 2017 */
            string solution = @"C:\Users\Simon\source\repos\WebApplication1\WebApplication1.sln";


            string project = "WebApplication1";
            //string projectItem = "WebForm1.aspx";

            object objSol = Marshal.BindToMoniker(solution); /* should bind if running */
            EnvDTE.Solution sol = (EnvDTE.Solution)objSol;     /* does a cast */

            /* next line does not compile with error message 
                Error   CS1061  
                'IQueryable' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'IQueryable' could be found (are you missing a using directive or an assembly reference?) AsQueryableConsoleApp   
             */
            IQueryable<EnvDTE.Project> query = sol.Projects.AsQueryable().Where(proj => proj.Name = project);
        }
    }
}

Solution

  • EnvDTE.Projects is not a 'generic collection', it only implements the non-generic IEnumerable (https://learn.microsoft.com/en-us/dotnet/api/envdte.projects?view=visualstudiosdk-2017)

    You need to convert to a generic IEnumerable<T> first, using Cast or OfType:

       var query = sol.Projects.OfType<EnvDTE.Project>().Where(proj => proj.Name == project);