Go to the documentation of this file.00001 using System;
00002 using System.Collections;
00003 using System.Collections.Generic;
00004 using System.Diagnostics;
00005 using System.Linq;
00006 using System.Linq.Expressions;
00007 using System.Reflection;
00008 using N2.Persistence.Finder;
00009
00010 namespace N2.Linq
00011 {
00012 public class ContentQuery<T> : IQueryable<T>
00013 {
00014 public ContentQuery(ContentQueryProvider queryProvider)
00015 {
00016 Provider = queryProvider;
00017 ElementType = typeof(T);
00018 Expression = Expression<T>.Constant(this);
00019 }
00020
00021 #region IEnumerable<T> Members
00022
00023 public IEnumerator<T> GetEnumerator()
00024 {
00025 return Provider.Execute<IEnumerable<T>>(Expression).GetEnumerator();
00026 }
00027
00028 #endregion
00029
00030 #region IEnumerable Members
00031
00032 IEnumerator IEnumerable.GetEnumerator()
00033 {
00034 return ((IEnumerable)Provider.Execute(Expression)).GetEnumerator();
00035 }
00036
00037 #endregion
00038
00039 #region IQueryable Members
00040
00041 public Type ElementType { get; set; }
00042
00043 public Expression Expression { get; set; }
00044
00045 public IQueryProvider Provider { get; set; }
00046
00047 #endregion
00048 }
00049 public class ContentQueryProvider : IQueryProvider
00050 {
00051 readonly IItemFinder finder;
00052
00053 public ContentQueryProvider(IItemFinder finder)
00054 {
00055 this.finder = finder;
00056 }
00057
00058 #region IQueryProvider Members
00059
00060 public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
00061 {
00062 return new ContentQuery<TElement>(this) { Expression = expression };
00063 }
00064
00065 public IQueryable CreateQuery(Expression expression)
00066 {
00067 throw new NotImplementedException();
00068 }
00069
00070 public TResult Execute<TResult>(Expression expression)
00071 {
00072 return (TResult)Execute(expression);
00073 }
00074
00075 public object Execute(Expression expression)
00076 {
00077 LambdaUtilities.PrintUnkwnown(expression);
00078 Type t = TypeSystem.GetElementType(expression.Type);
00079 ExpressionParser parser = new ExpressionParser(finder.Where.Type.Eq(t));
00080 return parser.Execute(expression);
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 }
00112
00113 private void AppendQuery(Expression expression, IQueryBuilder builder)
00114 {
00115
00116 }
00117
00118 object Finalize(string methodName, ConstantExpression ce, IQueryBuilder builder)
00119 {
00120 Type itemType = ((IQueryable)ce.Value).ElementType;
00121 IQueryAction action = builder.Type.Eq(itemType);
00122 if (methodName == "Count")
00123 return action.Count();
00124
00125 MethodInfo method = action.GetType().GetMethods().Where(m => m.Name == "Select" && m.IsGenericMethod).First();
00126 return method.MakeGenericMethod(itemType).Invoke(action, null);
00127 }
00128
00129 #endregion
00130 }
00131
00132 public class ExpressionParser
00133 {
00134 readonly IQueryAction builder;
00135
00136 public ExpressionParser(IQueryAction builder)
00137 {
00138 this.builder = builder;
00139 }
00140
00141 public object Execute(Expression expression)
00142 {
00143 if (expression.NodeType == ExpressionType.Call)
00144 {
00145 return new CallExpressionParser(builder).Execute(expression as MethodCallExpression);
00146 }
00147 throw new NotImplementedException();
00148 }
00149 }
00150
00151
00152 internal class CallExpressionParser
00153 {
00154 readonly IQueryAction builder;
00155
00156 public CallExpressionParser(IQueryAction builder)
00157 {
00158 this.builder = builder;
00159 }
00160
00161 public object Execute(MethodCallExpression expression)
00162 {
00163 if (expression.Method.Name == "Select")
00164 return builder.Select();
00165 throw new NotImplementedException();
00166 }
00167 }
00168
00169
00170 public class LambdaUtilities
00171 {
00172 public static int PrintUnkwnown(Expression expression)
00173 {
00174 if (expression == null)
00175 return Write("(null)");
00176
00177 if (expression is LambdaExpression)
00178 return Print(expression as LambdaExpression);
00179 if (expression is ParameterExpression)
00180 return PrintParameter(expression as ParameterExpression);
00181 if (expression is MemberExpression)
00182 return PrintMember(expression as MemberExpression);
00183 if (expression is BinaryExpression)
00184 return PrintBinary(expression as BinaryExpression);
00185 if (expression is ConstantExpression)
00186 return PrintConstant(expression as ConstantExpression);
00187 if (expression is MethodCallExpression)
00188 return PrintMethodCall(expression as MethodCallExpression);
00189 throw new NotImplementedException("Not implemented for " + expression.GetType());
00190 }
00191
00192 private static int PrintMethodCall(MethodCallExpression expression)
00193 {
00194 Write("ToString: " + expression);
00195 Write("GetType: " + expression.GetType());
00196 Write("NodeType: " + expression.NodeType);
00197 Write("Type: " + expression.Type);
00198 foreach (var argument in expression.Arguments)
00199 {
00200 Write("Argument: " + argument);
00201 }
00202 Write("Method.Name: " + expression.Method.Name);
00203 Write("Object: " + expression.Object);
00204 PrintUnkwnown(expression.Object);
00205
00206 return 0;
00207 }
00208
00209 private static int PrintConstant(ConstantExpression expression)
00210 {
00211 Write("ToString: " + expression);
00212 Write("GetType: " + expression.GetType());
00213 Write("NodeType: " + expression.NodeType);
00214 Write("Type: " + expression.Type);
00215 Write("Value: " + expression.Value);
00216 return 0;
00217 }
00218
00219 private static int Print(LambdaExpression expression)
00220 {
00221 Write("ToString: " + expression);
00222 Write("GetType: " + expression.GetType());
00223 Write("Body: " + expression.Body);
00224 PrintUnkwnown(expression.Body);
00225 Write("NodeType: " + expression.NodeType);
00226 Write("Parameters: " + expression.Parameters);
00227 Write("Parameters.Count: " + expression.Parameters.Count);
00228 for (int i = 0; i < expression.Parameters.Count; i++)
00229 {
00230 Write("Parameters[" + i + "]: " + expression.Parameters[i]);
00231 PrintUnkwnown(expression.Parameters[i]);
00232 }
00233 Write("Type: " + expression.Type);
00234 return 0;
00235 }
00236
00237 private static int PrintMember(MemberExpression expression)
00238 {
00239 Write("ToString: " + expression);
00240 Write("GetType: " + expression.GetType());
00241 Write("Expression: " + expression.Expression);
00242 PrintUnkwnown(expression.Expression);
00243 Write("Member: " + expression.Member);
00244 Write("NodeType: " + expression.NodeType);
00245 Write("Type: " + expression.Type);
00246 return 0;
00247 }
00248
00249 private static int PrintBinary(BinaryExpression expression)
00250 {
00251 Write("ToString: " + expression);
00252 Write("GetType: " + expression.GetType());
00253 Write("Conversion: " + expression.Conversion);
00254 Write("IsLifted: " + expression.IsLifted);
00255 Write("IsLiftedToNull: " + expression.IsLiftedToNull);
00256 Write("Left: " + expression.Left);
00257 PrintUnkwnown(expression.Left);
00258 Write("Method: " + expression.Method);
00259 Write("NodeType: " + expression.NodeType);
00260 Write("Right: " + expression.Right);
00261 PrintUnkwnown(expression.Right);
00262 Write("Type: " + expression.Type);
00263 return 0;
00264 }
00265
00266 private static int PrintParameter(ParameterExpression expression)
00267 {
00268 Write("ToString: " + expression);
00269 Write("GetType: " + expression.GetType());
00270 Write("Name: " + expression.Name);
00271 Write("NodeType: " + expression.NodeType);
00272 Write("Type: " + expression.Type);
00273 return 0;
00274 }
00275
00276 private static int Write(string text)
00277 {
00278 int length = new StackTrace().GetFrames().Length;
00279 for (int i = 15; i < length; i++)
00280 {
00281 Console.Write(' ');
00282 }
00283 Console.WriteLine(text);
00284 return 0;
00285 }
00286 }
00287
00288 internal static class TypeSystem
00289 {
00290 internal static Type GetElementType(Type seqType)
00291 {
00292 Type ienum = FindIEnumerable(seqType);
00293 if (ienum == null) return seqType;
00294 return ienum.GetGenericArguments()[0];
00295 }
00296
00297 private static Type FindIEnumerable(Type seqType)
00298 {
00299 if (seqType == null || seqType == typeof(string))
00300 return null;
00301
00302 if (seqType.IsArray)
00303 return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
00304
00305 if (seqType.IsGenericType)
00306 {
00307 foreach (Type arg in seqType.GetGenericArguments())
00308 {
00309 Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
00310 if (ienum.IsAssignableFrom(seqType))
00311 {
00312 return ienum;
00313 }
00314 }
00315 }
00316
00317 Type[] ifaces = seqType.GetInterfaces();
00318 if (ifaces != null && ifaces.Length > 0)
00319 {
00320 foreach (Type iface in ifaces)
00321 {
00322 Type ienum = FindIEnumerable(iface);
00323 if (ienum != null) return ienum;
00324 }
00325 }
00326
00327 if (seqType.BaseType != null && seqType.BaseType != typeof(object))
00328 {
00329 return FindIEnumerable(seqType.BaseType);
00330 }
00331
00332 return null;
00333
00334 }
00335
00336 }
00337 public static class Find<T> where T : ContentItem
00338 {
00339 public static IQueryable<T> Items
00340 {
00341 get { return new ContentQuery<T>(new ContentQueryProvider(Find.Items)); }
00342 }
00343 }
00344 }