So, is the set of "queries" input from a file or user input?
I'm assuming here that they are all of the form:
Std==int && Student==string
At least semantically, if not literally.
So here's a fairly massive implementation of what you asked for!
I should have declared some new classes to hold the "semantic" information.
(Maybe I'll write an article. This drove me into learning more about
Expression
s. Thanks!)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication21
{
class StudentType
{
public StudentType(int std, string id)
{
Std = std;
StudentID = id;
}
public int Std { get; set; }
public string StudentID { get; set; }
}
class Program
{
static List<Tuple<int, string>> QueryInputs = new List<Tuple<int, string>>
{ new Tuple<int, string>(8, "Student1"),
new Tuple<int, string>(8, "Student2"),
new Tuple<int, string>(8, "Student3"),
new Tuple<int, string>(9, "Student2"),
new Tuple<int, string>(9, "Student3") };
static List<StudentType> Student = new List<StudentType> {
new StudentType(7, "Student1"),
new StudentType(8, "Student0"),
new StudentType(8, "Student1"),
new StudentType(8, "Student3"),
new StudentType(8, "Student2"),
new StudentType(8, "Student10"),
new StudentType(9, "Student0"),
new StudentType(9, "Student2"),
new StudentType(10, "Student3"),
};
private static IEnumerable<StudentType> WhichStudents(IEnumerable<StudentType> students, Func<StudentType, bool> test)
{
return students.Where(test);
}
private static Dictionary<int, List<string>> QuerySemantics = new Dictionary<int, List<string>>();
private static MethodInfo ContainsInfo = typeof(List<string>).GetMethod("Contains");
private static MethodInfo WhichStudentsInfo = typeof(Program).GetMethod("WhichStudents", BindingFlags.NonPublic | BindingFlags.Static);
private static ParameterExpression ArgumentParameter = Expression.Parameter(typeof(StudentType), "s");
private static ParameterExpression OuterArgumentParameter = Expression.Parameter(typeof(IEnumerable<StudentType>), "students");
static void Main(string[] args)
{
foreach (var item in QueryInputs)
{
int queryStd = item.Item1;
string queryStudent = item.Item2;
List<string> studentList;
if (!QuerySemantics.TryGetValue(queryStd, out studentList))
{
studentList = new List<string>();
QuerySemantics.Add(queryStd, studentList);
}
studentList.Add(queryStudent);
}
Expression fullQueryExpression = null;
Dictionary<string, string> studentListMap = new Dictionary<string, string>();
Dictionary<string, BinaryExpression> studentListVariableExpressions = new Dictionary<string, BinaryExpression>();
int listCounter = 0;
foreach (var q in QuerySemantics)
{
var qStudents = q.Value;
if (qStudents.Count > 1)
{
qStudents.Sort();
string key = string.Concat(qStudents);
string listVar;
if (!studentListMap.TryGetValue(key, out listVar))
{
listVar = "sl" + (listCounter++).ToString();
studentListMap.Add(key, listVar);
var varExpression = Expression.Assign(Expression.Variable(typeof(List<string>), listVar),
Expression.ListInit(Expression.New(typeof(List<string>)),
qStudents.Select(s => Expression.Constant(s))));
studentListVariableExpressions.Add(listVar, varExpression);
}
qStudents.Insert(0, listVar);
}
}
foreach (var q in QuerySemantics)
{
Expression queryExpression = null;
var qStdExpression = Expression.Equal(Expression.Constant(q.Key),
Expression.Property(ArgumentParameter, "Std"));
var qStudents = q.Value;
Expression qStudentsExpression = null;
if (qStudents.Count > 1)
{
var studentListVar = studentListVariableExpressions[qStudents[0]];
qStudentsExpression = Expression.Call(studentListVar.Left, ContainsInfo,
Expression.Property(ArgumentParameter, "StudentID"));
}
else
{
qStudentsExpression = Expression.Equal(Expression.Constant(qStudents[0]),
Expression.Property(ArgumentParameter, "StudentID"));
}
queryExpression = Expression.AndAlso(qStdExpression, qStudentsExpression);
if (fullQueryExpression == null)
{
fullQueryExpression = queryExpression;
}
else
{
fullQueryExpression = Expression.OrElse(fullQueryExpression, queryExpression);
}
}
var lambdaQueryExpression = Expression.Lambda<Func<StudentType, bool>>(fullQueryExpression, ArgumentParameter);
var variables = studentListVariableExpressions.Values.Select(lve => lve.Left).Cast<ParameterExpression>();
var expressionsList = studentListVariableExpressions.Values.Cast<Expression>().ToList();
expressionsList.Add(Expression.Call(WhichStudentsInfo, OuterArgumentParameter, lambdaQueryExpression));
var whichStudentsBlock = Expression.Block(typeof(IEnumerable<StudentType>), variables, expressionsList);
var lambdaWhichStudentsExpression = Expression.Lambda<Func<IEnumerable<StudentType>,
IEnumerable<StudentType>>>(whichStudentsBlock,
OuterArgumentParameter);
var compiled = lambdaWhichStudentsExpression.Compile();
foreach (var s in compiled(Student))
{
Console.WriteLine("Std: {0}, StudentID: {1}", s.Std, s.StudentID);
}
}
}
}