Tutorial :C# - Help with LINQ



Question:

I need to check if a certain property exists within a class. Please refer to the LINQ query in question. For the life of me I cannot make the compiler happy.

class Program  {      static void Main(string[] args)      {          ModuleManager m = new ModuleManager();          IModule module = m.FindModuleForView(typeof(HomeView));          Console.WriteLine(module.GetType().ToString());          Console.ReadLine();      }  }    public class ModuleManager  {      [ImportMany]      public IEnumerable<Lazy<IModule>> Modules { get; set; }        [ImportMany]      public IEnumerable<Lazy<View>> Views { get; set; }        public ModuleManager()      {          //An aggregate catalog that combines multiple catalogs          var catalog = new AggregateCatalog();          //Adds all the parts found in the same assembly as the Program class          catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));          //Create the CompositionContainer with the parts in the catalog          _container = new CompositionContainer(catalog);          //Fill the imports of this object          try          {              this._container.ComposeParts(this);          }          catch (CompositionException compositionException)          {              Console.WriteLine(compositionException.ToString());          }      }        public IModule FindModuleForView(Type view)      {          //THIS IS THE PROBLEM          var module = from m in Modules                       where (                          from p in m.Value.GetType().GetProperties()                          where p.GetType().Equals(view)                          select p                       )                       select m;        }      public CompositionContainer _container { get; set; }  }    public interface IModule  {  }    [Export]  public class HomeModule : IModule  {      public HomeModule()      {      }        [Export]      public HomeView MyHomeView      {          get          {              return new HomeView();          }          set          {          }      }  }      public class HomeView : View  {  }    public class View  {  }  


Solution:1

The inner query should return bool, but returns PropertyInfo.

I haven't tested this, but I think you want something like:

    var module = (from m in Modules                   where m.Value.GetType().GetProperties()                      .Select(p => p.PropertyType).Contains(view)                   select m).FirstOrDefault();  

Edit:

Incorporating the Enumerable.Any suggestion on another answer:

    var module = (from m in Modules                   where m.Value.GetType().GetProperties()                      .Any(p => p.PropertyType.Equals(view))                   select m).FirstOrDefault();  


Solution:2

GetProperties() returns an array of PropertyInfo objects. Your call to p.GetType() is always going to return typeof(PropertyInfo) - never the "view" type you've passed in.

You probably want this instead:

from p in m.Value.GetType().GetProperties()   where p.PropertyType.Equals(view)   select p   

Edit

As Robert pointed out, your logic to determine if the above query returns any properties is also wrong. An easy way around that is to see if anything came back from the subquery:

var module = from m in Modules                where (                    from p in m.Value.GetType().GetProperties()                    where p.PropertyType.Equals(view)                    select p                ).Any()               select m  

Keep in mind that that query might return more than one module. You will probably want to return .First() from the results.


Solution:3

The where keyword expects a predicate that returns a boolean condition, but you are providing a subquery that returns an IEnumerable. Can you rework your subquery so that it returns an actual boolean condition?

You can convert it to a boolean result by using the FirstOrDefault() extension method. This method will return null if there are no records. So this should work (untested):

where ( from p in m.Value.GetType().GetProperties()           where p.PropertyType.Equals(view)           select p ).FirstOrDefault() != null  


Solution:4

Even if you can get your query working, I don't think this is a good way to link your model with your view. I'd recommend creating a new question with more detail about what you are trying to do (and why), asking how you can create the association/link between the model and the view.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »