Linq query with curly braces for anonymous action/function body

Go To StackoverFlow.com

2

I have this entities:

public class Parent: AllDependant
{
    /*Properties goes here*/
}

public class Children: AllDependant
{
    /*Properties goes here*/
}

Then I have allDependants variable with typeof List<AllDependant> which will keep some of parents and childrens entitiy in mix.

Later on, I want to select from them and do something like this:

var selectedDependantInfos = allDependants
        .Select(dependant =>
        {
            if (dependant is Parent)
            {
                var parent = dependant as Parent;
                return new { Name = parent.Name, SomeSpecialInfo = parent.ParentInfo };
            }
            else
            {
                var child = dependant as Children;
                return new { Name = child.Name, SomeSpecialInfo = child.ChildInfo }
            }
        });

Note the specific property for child and parent require me to cast and get the property to a new model for UI display which is not entity concern. I cannot put the special property in AllDependant base class because I need to refactor the property name on so many files including *.ascx which is troublesome. However it done by using the Linq Select extension method above but I just thinking of this:

Question: How can I do the same in Linq Query?

This will give error on the select keyword and the curly braces:

var selectedDependantInfos = from dependant in allDependants
                            select
                            {
                                /* the same if statement goes here */
                            }
2012-04-04 06:13
by CallMeLaNN
What do you think you will gain by changing it into Linq syntax - ChrisWue 2012-04-04 06:17
The error is because you're missing the new keyword. select new { .. } - alexn 2012-04-04 06:18
@ChrisWue, not changing just thinking how to do function body in Linq query just like we can do function body in Lambda - CallMeLaNN 2012-04-04 08:15


3

You would use the conditional operator and get something like

  from dependant in allDependants             
  select dependant is Parent 
         ? new { Name = (dependant as Parent).Name,  /* Parent fields */ }
         : new { Name = (dependant as Children).Name, /* Child fields */ }

But as you see that is not a great improvement. There's no convenient place to do the type-cast.

The better option would seem to move the Name and SpecialInfo properties to a base class (AllDependant or a special intermediate class).

2012-04-04 06:25
by Henk Holterman
+1 for the last paragraph. Note that a Sibling class in allDependants will result in NullReferenceException here - InvalidCastException is always more informative, so I'd use a cast - Jacek Gorgoń 2012-04-04 07:12
Thanks, almost there, but maybe I want to change the question to How can I create Linq query with action/function body instead of expression just like how we can do within Lambda using curly braces - CallMeLaNN 2012-04-04 08:21
You can do (from d in ...).Select(x => x) - Henk Holterman 2012-04-04 08:42
I see, so it seems like not possible to have curly braces in the Linq query but after that we can combined with extension method to have function body in lambda expression. Nice - CallMeLaNN 2012-04-04 13:10


2

An alternative would be:

var parents = allDependants.OfType<Parent>.Select(p => new { Name =  p.Name, .... };
var children = allDependants.OfType<Children>.Select(c => new { Name =  c.Name, .... };

var combined = parents.Concat(children);

The disadvantage of this approach would be that addDependants would be iterated over twice.

2012-04-04 06:56
by Phil
This will iterate over allDependants twice and perform the type check twice but on the other hand is safe if allDependants will contain an AllDependant not being Parent or Child (as opposed to OP solution) - Jacek Gorgoń 2012-04-04 07:09
Yes you're correct. I'll add a note - Phil 2012-04-04 07:10
Oh, ya, it just alternative to my example, but it is not the answer :) actually I want to know how I can do the same by using Linq quer - CallMeLaNN 2012-04-04 08:18
It is a Linq query. Isn't it - Phil 2012-04-04 08:20
I mean I want to convert from using Linq extension method in the example above to Linq query using from e in entities select e.column syntax - CallMeLaNN 2012-04-04 13:15


0

Another way of using Reflection

var selectedDependantInfos = from p in allDependants
                         let key = p is Parent ? "ParentInfo" : "ChildInfo"
                         select new { 
                             Name = p.GetType().GetProperty("Name").GetValue(p, null).ToString(), 
                             SomeSpecialInfo = p.GetType().GetProperty(key).GetValue(p, null).ToString() 
                         };
2012-04-04 07:19
by shenhengbin
While this might work it's not a good thing to do: performance is bad (compared to the original approach) and it's refactoring unfriendl - ChrisWue 2012-04-04 08:19
@ChrisWue Reflection performance will depend on the implementation. Like p.GetType().GetProperty("Name") would be cached. You can found such implementation in many ORM frameworks - shenhengbin 2012-04-04 08:25
Ads