1

I want to dynamically add .Select statements, but the compiler will only allow me to build these statements inside the current scope. I am aware of linqkit, which could be a solution, but i dont want to add any external functionallity. How do i avoid this code duplication which i have now:

 if (request.Equals("some text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }
        //Same thing again but slightly different
        else if (request.Equals("some other text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                    x.Timestamp.Day
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    Day= g.Key.Day,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }
3
  • What is you data source for the linq query? If it is 'Linq to objects' you can invoke a variable delegate. Commented Jun 18, 2012 at 14:11
  • 2
    Not sure I understand your actual problem. Couldn't you use named types instead of anonymous one ? you could create a class with all the column fields and create two constructors or a static method to build an instance from a filter ? Commented Jun 18, 2012 at 14:20
  • yes i could use named types, however i failed to try and define it. How should I declare it? Commented Jun 19, 2012 at 6:17

2 Answers 2

1

If you want to maintain the Anonymous type you can use the InternalsVisibleToAttribute to allow a separate common library to work with the anonymous type.

I have done this previously to make a generic filtering library for datagrids with EF data sources, but it does involve a level of reflection and building the expression out of generic System.Linq.Expression components so this may not be worthwhile unless you have very many instances you want to do this to.

See msdn info:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

and

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

If the select pattern is more predicable you may not need the expression portion, but in that case it may ultimately be simpler to just use a public class instead of the anonymous one.

Edit: "cannot convert anonymous to x" type errors mean you haven't gotten rid of the anonymous entirely/correctly.

In each of the locations you have new { ...whatever... } you are creating an anonymous type. If you create classes for each of those that have the correct properties to match what you are assigning then you just change something that looks like

new {x=1,y=2}

to read

new somenewclass() {x=1,x=2}

assuming you have defined elsewhere

public class somenewclass
{
    public int x {get;set;}
    public int y {get;set;}
}
Sign up to request clarification or add additional context in comments.

2 Comments

yes I will try defining a public class instead. But i get all kinds of error messages when I try to create a class instead, saying cannot implicitly convert from anonymous type to my class
Not exactly the answer i was looking for, but you helped me on the right track, so i accept this as answer
0

You can do like this ,

  var Query = commonFilter.Select(g => new
            {
                Year = g.Key.Year,
                Month = g.Key.Month,
                Day= g.Key.Day,
                TotErr = g.Count(),

                column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                NumUsers = g.Select(l => l.UserId).Distinct().Count(),

            });
    if (request.Equals("some text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
            }) ;
    }
    //Same thing again but slightly different
    else if (request.Equals("some other text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
                x.Timestamp.Day
            });
    }

2 Comments

nice idea, but couldnt get it to work. How could the variable query in your example, evaluate for example Year= g.Key.Year, when the grouping hasent even been declared yet?
My bad, I missed that point in a glitch, but at least it can be a starting point and can be refined further.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.