简体   繁体   中英

Using C# Linq find and return a string value from a multi-level data store

I have a custom config stored in memory DomainConfigElements .

  <RemoteAppConfiguration>
    <domains>
      <domain name="abc" isenabled="true">
        <remoteapps>
          <remoteapp name="app1" applicationname="app1shortcut" isenabled="true" />
          <remoteapp name="app2" applicationname="app2shortcut" isenabled="true" />
        </remoteapps>
      </domain>
      <domain name="efg" isenabled="false">
        <remoteapps>
          <remoteapp name="app3" applicationname="app3exe" isenabled="true" />
          <remoteapp name="app4" applicationname="app4exe" isenabled="true" />
        </remoteapps>        
      </domain>
      <domain name="xyz" isenabled="true">
        <remoteapps>
          <remoteapp name="app5" applicationname="app5launcher" isenabled="true" />
          <remoteapp name="app6" applicationname="app6launcher" isenabled="true" />
        </remoteapps>        
      </domain>
    </domains>    
  </RemoteAppConfiguration>

I have to find an app app5 and return the applicationanme . In this example, I have to return a string app5launcher . If I pass app2 then the code should return app2shortcut .

I wanted to use linq to get the desired result. This is what I came with:

var fixedParam = "app6";
var apps = AppUtilities.DomainConfigElements.Where(d => d.IsEnabled)
         .Select(d => d.RemoteApps
         .Where(r => string.Equals(r.Name, fixedParam, StringComparison.InvariantCultureIgnoreCase))).FirstOrDefault();
var appName = apps.Select(a => a.ApplicationName).FirstOrDefault();

It gets me the result, but looks complex. I feel this can be simplified. I wanted to know is there a better way of doing this? I tried to ask this question in codereview.stackexchange but the website seems to be not working right now.

Updated answer:

The original LINQ query you posted is picking a list of RemoteApp that match the criteria Name to fixedParam . The final .FirstOrDefault() query in the first LINQ statement picks first item from that list and stores in apps .

2nd LINQ query apps.Select(a => a.ApplicationName).FirstOrDefault(); just picks ApplicationName attribute from apps , which should only be one item anyway. Then, FirstOrDefault() is called again.

The main reason this is inefficient is because of redundant FirstOrDefault() calls. However, it does handle case where multiple RemoteApp items have same Name attribute.

My solution starts by picking enabled Domain object from DomainConfigElements . There is an additional query in here that ensures the Domain being picked also contains the RemoteApp object with Name == FixedParam . Once the correct Domain is selected, I query on RemoteApps in the domain and pick RemoteApp that matches Name == fixedParam . Then, we just get ApplicationName property.

AppUtilities.DomainConfigElements
                .Where(d => d.IsEnabled) // get enabled domains
                .Select(d => d.RemoteApps // query on remote apps inside domain
                    .FirstOrDefault(app => app.Name == "app2")) 
                .FirstOrDefault(d => d.Name == "app2").ApplicationName; // query on fixedParam

I mocked up your class structure in my own IDE to get the statements correct, but I have not run it against your XML yet. Let me know if this works for you, otherwise I will remove:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM