Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It seems like if we could dynamically generate the equivalent of the expression: x => new { a = x.Prop1, b = x.Prop2, ... } Then a reasonable LINQ => SQL provider would probably generate the SQL you want. Generating a new anonymous type on the fly seems hard, but we could take advantage of the fact that anonymous types are generic to re-use one.</p> <pre><code>// at the top of your class private static readonly object AnonymousObjectWithLotsOfProperties = new { a = 1, b = 2, ... }; // then in your method // (1) first get the list of properties represented by the string you passed in (I assume you know how to do this via reflection) var props = typeof(T).GetProperties().Where(...); var propTypes = props.Select(pi =&gt; pi.PropertyType).ToList(); // (2) now generate the correctly genericized anonymous type to use var genericTupleType = AnonymousObjectWithLotsOfProperties.GetType() .GetGenericTypeDefinition(); // for generic args, use the prop types and pad with int var genericArguments = propTypes.Concat(Enumerable.Repeat(typeof(int), genericTupleType.GetProperties().Length - propTypes.Count)) .ToArray(); var tupleType = genericTupleType.MakeGenericType(genericArguments); // (3) now we have to generate the x =&gt; new { ... } expression // if you inspect "System.Linq.Expressions.Expression&lt;Func&lt;object&gt;&gt; exp = () =&gt; new { a = 2, b = 3 };" // in the VS debugger, you can see that this is actually a call to a constructor // on the anonymous type with 1 argument per property var tParameter = Expression.Parameter(typeof(T)); // create the expression var newExpression = Expression.New( constructor: tupleType.GetConstructors().Single(), // get the one constructor we need // the arguments are member accesses on the parameter of type T, padded with 0 arguments: props.Select(pi =&gt; Expression.MakeMemberAccess(tParameter, pi)) .Concat(Enumerable.Repeat(Expression.Constant(0), genericTupleType.GetProperties().Length - propTypes.Count)) ); // create the lambda: we need an Expression&lt;TDelegate&gt;, which means that we // need to get the generic factory method from Expression and invoke it var lambdaGenericMethod = typeof(Expression).GetMethods(BindingFlags.Static | BindingFlags.Public) .Single(m =&gt; m.IsGenericMethodDefinition); var lambdaMethod = lambdaGenericMethod.MakeGenericMethod(typeof(Func&lt;,&gt;).MakeGenericType(typeof(T), tupleType)); // reflection for Expression.Lambda(body, parameters) var lambda = lambdaGenericMethod.Invoke(null, new object[] { newExpression, new[] { tParameter }); // now that we have the expression, we can invoke GroupBy via reflection. // Of course, that leaves you with an IQueryable&lt;IGrouping&lt;ANON, T&gt;&gt;, which isn't much // use until you apply some other IQueryable methods to eliminate the ANON type from the // method signature so you can return it </code></pre> <p>Note that I didn't actually get to compile and run this code, so I can't promise that everything above is perfect. However, hopefully it will put you on the right track.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload