Andrew Morpeth
Andrew Morpeth

Reputation: 167

Using Linq to query nested dynamic objects

I have used the following linq query to access the member Names. The following successfully returns all member Name values within the collection.

var we = CsQ.Groups.SelectMany(g => g.Members).Where(a => a.Name == "Name").Select(b => b.Value).ToList();

I want to now filter this down based another property within "Members" called AbsoluteUri which is nested in a property AgentsByUri. This doesnt work but gives an idea of the structure:

var uri = CsQ.Groups.SelectMany(g => g.Members).Where(a => a.Name == "AgentsByUri").Select(b => b.Value).//??? I NEED TO NOW ACCESS "AbsoluteUri"

How can I combine these in to one query so that I can return only the "Names" that have an "AbsoluteUri" that contains "SomeValue". AbsoluteUri seems to be nested in a collection thats nested in AgentsByUri which adds to the complication.

You can see the structure of the AgentsByUri object here - Using C# Linq to query nested objects

Excuse my terminology, I'm reasonably new to C#! Hopefully this makes sense :)

Any help or guidance VERY appreciate :)

EDIT3 Getting somewhere! Casting as dynamic partially working - member.AgentsByUri is now OK, just cant figure out how to make it apply to the rest of the query. Tried adding in various locations by no luck.

Cast as dynamic

EDIT2 Thanks for everyone's input. I haven't had any further success. I think the biggest problem is that I am dealing with a PowerShell object which is dynamically generated at run time. As a result I cannot access the classes/object because the compiler doesn't yet no about them. To get around this I use the "dynamic" type which allows the compiler to trust that what I provide will be valid at run time. Can I cast as dynamic in a linq query? Or do I need to go about this in a different way?

Heres what I get with the examples give:

Compiler error when trying to access dynamic object

EDIT1 (click and zoom, image is high res): Data Structures

Upvotes: 0

Views: 1910

Answers (3)

Michael Spranger
Michael Spranger

Reputation: 495

I'm just writing this down, based on the image you provided. However, I can not check for correctness without the surrounding code, so no guarantees.

var uri = CsQ.Groups
    .SelectMany(g => g.Members)
    .Where(m => m.AgentsByUri.SelectMany(a => a.Value, (a, v) => v.AbsoluteUri).Contains("SomeValue"))
    .Select(b => b.Value)

In LINQ syntax it should be much clearer

var uri =
    from group in CsQ.Groups
    from dynamic member in group.Members
    where
        (from agent in (IEnumerable<dynamic>)member.AgentsByUri
         where agent.Name = "AgentsByUri"  // this line may be redundant
         from x in (IEnumerable<dynamic>)agent.Value
         select x.AbsoluteUri).Contains("SomeValue")
    select member.Value;

EDIT: The suggestion in my second comment does not quite work. I changed the code in LINQ syntax above to account for dynamic objects as the source by explicitly casting to IEnumerable<dynamic>. Note however that the cast will fail for an enumeration of a value type. I hope this will work for you.

Upvotes: 1

ertdiddy
ertdiddy

Reputation: 407

I had to do some digging and make a few assumptions here:

  1. You want to return a list of PSMemberInfo.
  2. PsMemberInfo.Name must equal "AgentsByUri".
  3. In the Value property (which is a collection of Uri), you want to filter this collection on items whose AbsoluteUri property equals "SomeValue".
var we = CsQ.Groups.SelectMany(g => g.Members).Where(member => member.Name == "AgentsByUri" && member.Value != null && member.Value.Any(uri => uri.AbsoluteUri == "SomeValue")).ToList();

Upvotes: 1

Tim Pohlmann
Tim Pohlmann

Reputation: 4440

It's hard to give a proper answer without having a proper overview of the class structure. I guess this might work:

var uri = CsQ.Groups.SelectMany(g => g.Members).Where(a => a.Name == "AgentsByUri").Select(b => b.Value).Where(x => x.AbsoluteUri == "SomeValue");

Upvotes: 1

Related Questions