2012年7月3日星期二

ASP.NET MVC 3 直到我膝盖中了一箭【11】MVC3MusicStore排序

ASP.NET MVC 3 直到我膝盖中了一箭【11】MVC3MusicStore排序

1.~/Resources/下添加资源文件Resource

2.~/Views/StoreManager/下更新视图Index

View Code
 1 @model IEnumerable<MVC3MusicStore.Models.Album> 2 @helper Truncate(string input, int length) 3     { 4         if (input.Length <= length) 5         { 6     @input 7         } 8         else 9         {10     @input.Substring(0, length)<text>...</text>11 12         }13 }14 @{15     ViewBag.Title = "Index";16 }17 @using MVC3MusicStore.Helpers18 <h2>19     Index</h2>20 <p>21     @Html.ActionLink((string)ViewBag.CreateLink, "Create")22 </p>23 <table>24     <tr>25         <th>26             @Html.ActionLink((string)ViewBag.GenreDisplay, "Index", new { sortOrder = ViewBag.GenreSortParam })27         </th>28         <th>29             @Html.ActionLink((string)ViewBag.ArtistDisplay, "Index", new { sortOrder = ViewBag.ArtistSortParam })30         </th>31         <th>32             @Html.ActionLink((string)ViewBag.TitleDisplay, "Index", new { sortOrder = ViewBag.TitleSortParam })33         </th>34         <th>35             @Html.ActionLink((string)ViewBag.PriceDisplay, "Index", new { sortOrder = ViewBag.PriceSortParam })36         </th>37         @*        <th>38             AlbumArtUrl39         </th>*@40         <th>41         </th>42     </tr>43     @foreach (var item in Model)44     {45         <tr>46             <td>47                 @*@item.GenreId*@48                 @Html.DisplayFor(modelItem => item.Genre.Name)49             </td>50             <td>51                 @*@item.ArtistId*@ @*@Html.DisplayFor(modelItem => item.Artist.Name)*@52                 @Truncate(item.Artist.Name, 25)53             </td>54             <td>55                 @*@item.Title*@56                 @Truncate(item.Title, 25)57             </td>58             <td>59                 @*@String.Format("{0:F}", item.Price)*@60                 @Html.DisplayFor(modelItem => item.Price)61             </td>62             @*            <td>63                 @item.AlbumArtUrl64             </td>*@65             <td>66                 @Html.ActionLink((string)ViewBag.EditLink, "Edit", new { id = item.AlbumId })|67                 @Html.ActionLink((string)ViewBag.DetailsLink, "Details", new { id = item.AlbumId })|68                 @Html.ActionLink((string)ViewBag.DeleteLink, "Delete", new { id = item.AlbumId })69             </td>70         </tr>71     }72 </table>

3.使用LINQ Dynamic Query Library

  将DynamicQuery文件夹中的Dynamic源文件copy至项目中,添加命名空间"using System.Linq.Dynamic",这样你就可以使用它了。

View Code
   1 //Copyright (C) Microsoft Corporation.  All rights reserved.   2    3 using System;   4 using System.Collections.Generic;   5 using System.Text;   6 using System.Linq;   7 using System.Linq.Expressions;   8 using System.Reflection;   9 using System.Reflection.Emit;  10 using System.Threading;  11   12 namespace System.Linq.Dynamic  13 {  14     public static class DynamicQueryable  15     {  16         public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values) {  17             return (IQueryable<T>)Where((IQueryable)source, predicate, values);  18         }  19   20         public static IQueryable Where(this IQueryable source, string predicate, params object[] values) {  21             if (source == null) throw new ArgumentNullException("source");  22             if (predicate == null) throw new ArgumentNullException("predicate");  23             LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);  24             return source.Provider.CreateQuery(  25                 Expression.Call(  26                     typeof(Queryable), "Where",  27                     new Type[] { source.ElementType },  28                     source.Expression, Expression.Quote(lambda)));  29         }  30   31         public static IQueryable Select(this IQueryable source, string selector, params object[] values) {  32             if (source == null) throw new ArgumentNullException("source");  33             if (selector == null) throw new ArgumentNullException("selector");  34             LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);  35             return source.Provider.CreateQuery(  36                 Expression.Call(  37                     typeof(Queryable), "Select",  38                     new Type[] { source.ElementType, lambda.Body.Type },  39                     source.Expression, Expression.Quote(lambda)));  40         }  41   42         public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {  43             return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);  44         }  45   46         public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) {  47             if (source == null) throw new ArgumentNullException("source");  48             if (ordering == null) throw new ArgumentNullException("ordering");  49             ParameterExpression[] parameters = new ParameterExpression[] {  50                 Expression.Parameter(source.ElementType, "") };  51             ExpressionParser parser = new ExpressionParser(parameters, ordering, values);  52             IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();  53             Expression queryExpr = source.Expression;  54             string methodAsc = "OrderBy";  55             string methodDesc = "OrderByDescending";  56             foreach (DynamicOrdering o in orderings) {  57                 queryExpr = Expression.Call(  58                     typeof(Queryable), o.Ascending ? methodAsc : methodDesc,  59                     new Type[] { source.ElementType, o.Selector.Type },  60                     queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));  61                 methodAsc = "ThenBy";  62                 methodDesc = "ThenByDescending";  63             }  64             return source.Provider.CreateQuery(queryExpr);  65         }  66   67         public static IQueryable Take(this IQueryable source, int count) {  68             if (source == null) throw new ArgumentNullException("source");  69             return source.Provider.CreateQuery(  70                 Expression.Call(  71                     typeof(Queryable), "Take",  72                     new Type[] { source.ElementType },  73                     source.Expression, Expression.Constant(count)));  74         }  75   76         public static IQueryable Skip(this IQueryable source, int count) {  77             if (source == null) throw new ArgumentNullException("source");  78             return source.Provider.CreateQuery(  79                 Expression.Call(  80                     typeof(Queryable), "Skip",  81                     new Type[] { source.ElementType },  82                     source.Expression, Expression.Constant(count)));  83         }  84   85         public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values) {  86             if (source == null) throw new ArgumentNullException("source");  87             if (keySelector == null) throw new ArgumentNullException("keySelector");  88             if (elementSelector == null) throw new ArgumentNullException("elementSelector");  89             LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values);  90             LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values);  91             return source.Provider.CreateQuery(  92                 Expression.Call(  93                     typeof(Queryable), "GroupBy",  94                     new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },  95                     source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));  96         }  97   98         public static bool Any(this IQueryable source) {  99             if (source == null) throw new ArgumentNullException("source"); 100             return (bool)source.Provider.Execute( 101                 Expression.Call( 102                     typeof(Queryable), "Any", 103                     new Type[] { source.ElementType }, source.Expression)); 104         } 105  106         public static int Count(this IQueryable source) { 107             if (source == null) throw new ArgumentNullException("source"); 108             return (int)source.Provider.Execute( 109                 Expression.Call( 110                     typeof(Queryable), "Count", 111                     new Type[] { source.ElementType }, source.Expression)); 112         } 113     } 114  115     public abstract class DynamicClass 116     { 117         public override string ToString() { 118             PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 119             StringBuilder sb = new StringBuilder(); 120             sb.Append("{"); 121             for (int i = 0; i < props.Length; i++) { 122                 if (i > 0) sb.Append(", "); 123                 sb.Append(props[i].Name); 124                 sb.Append("="); 125                 sb.Append(props[i].GetValue(this, null)); 126             } 127             sb.Append("}"); 128             return sb.ToString(); 129         } 130     } 131  132     public class DynamicProperty 133     { 134         string name; 135         Type type; 136  137         public DynamicProperty(string name, Type type) { 138             if (name == null) throw new ArgumentNullException("name"); 139             if (type == null) throw new ArgumentNullException("type"); 140             this.name = name; 141             this.type = type; 142         } 143  144         public string Name { 145             get { return name; } 146         } 147  148         public Type Type { 149             get { return type; } 150         } 151     } 152  153     public static class DynamicExpression 154     { 155         public static Expression Parse(Type resultType, string expression, params object[] values) { 156             ExpressionParser parser = new ExpressionParser(null, expression, values); 157             return parser.Parse(resultType); 158         } 159  160         public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values) { 161             return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, values); 162         } 163  164         public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values) { 165             ExpressionParser parser = new ExpressionParser(parameters, expression, values); 166             return Expression.Lambda(parser.Parse(resultType), parameters); 167         } 168  169         public static Expression<Func<T, S>> ParseLambda<T, S>(string expression, params object[] values) { 170             return (Expression<Func<T, S>>)ParseLambda(typeof(T), typeof(S), expression, values); 171         } 172  173         public static Type CreateClass(params DynamicProperty[] properties) { 174             return ClassFactory.Instance.GetDynamicClass(properties); 175         } 176  177         public static Type CreateClass(IEnumerable<DynamicProperty> properties) { 178             return ClassFactory.Instance.GetDynamicClass(properties); 179         } 180     } 181  182     internal class DynamicOrdering 183     { 184         public Expression Selector; 185         public bool Ascending; 186     } 187  188     internal class Signature : IEquatable<Signature> 189     { 190         public DynamicProperty[] properties; 191         public int hashCode; 192  193         public Signature(IEnumerable<DynamicProperty> properties) { 194             this.properties = properties.ToArray(); 195             hashCode = 0; 196             foreach (DynamicProperty p in properties) { 197                 hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode(); 198             } 199         } 200  201         public override int GetHashCode() { 202             return hashCode; 203         } 204  205         public override bool Equals(object obj) { 206             return obj is Signature ? Equals((Signature)obj) : false; 207         } 208  209         public bool Equals(Signature other) { 210             if (properties.Length != other.properties.Length) return false; 211             for (int i = 0; i < properties.Length; i++) { 212                 if (properties[i].Name != other.properties[i].Name || 213                     properties[i].Type != other.properties[i].Type) return false; 214             } 215             return true; 216         } 217     } 218  219     internal class ClassFactory 220     { 221         public static readonly ClassFactory Instance = new ClassFactory(); 222  223         static ClassFactory() { }  // Trigger lazy initialization of static fields 224  225         ModuleBuilder module; 226         Dictionary<Signature, Type> classes; 227         int classCount; 228         ReaderWriterLock rwLock; 229  230         private ClassFactory() { 231             AssemblyName name = new AssemblyName("DynamicClasses"); 232             AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); 233 #if ENABLE_LINQ_PARTIAL_TRUST 234             new ReflectionPermission(PermissionState.Unrestricted).Assert(); 235 #endif 236             try { 237                 module = assembly.DefineDynamicModule("Module"); 238             } 239             finally { 240 #if ENABLE_LINQ_PARTIAL_TRUST 241                 PermissionSet.RevertAssert(); 242 #endif 243             } 244             classes = new Dictionary<Signature, Type>(); 245             rwLock = new ReaderWriterLock(); 246         } 247  248         public Type GetDynamicClass(IEnumerable<DynamicProperty> properties) { 249             rwLock.AcquireReaderLock(Timeout.Infinite); 250             try { 251                 Signature signature = new Signature(properties); 252                 Type type; 253                 if (!classes.TryGetValue(signature, out type)) { 254                     type = CreateDynamicClass(signature.properties); 255                     classes.Add(signature, type); 256                 } 257                 return type; 258             } 259             finally { 260                 rwLock.ReleaseReaderLock(); 261             } 262         } 263  264         Type CreateDynamicClass(DynamicProperty[] properties) { 265             LockCookie cookie = rwLock.UpgradeToWriterLock(Timeout.Infinite); 266             try { 267                 string typeName = "DynamicClass" + (classCount + 1); 268 #if ENABLE_LINQ_PARTIAL_TRUST 269                 new ReflectionPermission(PermissionState.Unrestricted).Assert(); 270 #endif 271                 try { 272                     TypeBuilder tb = this.module.DefineType(typeName, TypeAttributes.Class | 273                         TypeAttributes.Public, typeof(DynamicClass)); 274                     FieldInfo[] fields = GenerateProperties(tb, properties); 275                     GenerateEquals(tb, fields); 276                     GenerateGetHashCode(tb, fields); 277                     Type result = tb.CreateType(); 278                     classCount++; 279                     return result; 280                 } 281                 finally { 282 #if ENABLE_LINQ_PARTIAL_TRUST 283                     PermissionSet.RevertAssert(); 284 #endif 285                 } 286             } 287             finally { 288                 rwLock.DowngradeFromWriterLock(ref cookie); 289             } 290         } 291  292         FieldInfo[] GenerateProperties(TypeBuilder tb, DynamicProperty[] properties) { 293             FieldInfo[] fields = new FieldBuilder[properties.Length]; 294             for (int i = 0; i < properties.Length; i++) { 295                 DynamicProperty dp = properties[i]; 296                 FieldBuilder fb = tb.DefineField("_" + dp.Name, dp.Type, FieldAttributes.Private); 297                 PropertyBuilder pb = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, null); 298                 MethodBuilder mbGet = tb.DefineMethod("get_" + dp.Name, 299                     MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, 300                     dp.Type, Type.EmptyTypes); 301                 ILGenerator genGet = mbGet.GetILGenerator(); 302                 genGet.Emit(OpCodes.Ldarg_0); 303                 genGet.Emit(OpCodes.Ldfld, fb); 304                 genGet.Emit(OpCodes.Ret); 305                 MethodBuilder mbSet = tb.DefineMethod("set_" + dp.Name, 306                     MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, 307                     null, new Type[] { dp.Type }); 308                 ILGenerator genSet = mbSet.GetILGenerator(); 309                 genSet.Emit(OpCodes.Ldarg_0); 310                 genSet.Emit(OpCodes.Ldarg_1); 311                 genSet.Emit(OpCodes.Stfld, fb); 312                 genSet.Emit(OpCodes.Ret); 313                 pb.SetGetMethod(mbGet); 314                 pb.SetSetMethod(mbSet); 315                 fields[i] = fb; 316             } 317             return fields; 318         } 319  320         void GenerateEquals(TypeBuilder tb, FieldInfo[] fields) { 321             MethodBuilder mb = tb.DefineMethod("Equals", 322                 MethodAttributes.Public | MethodAttributes.ReuseSlot | 323                 MethodAttributes.Virtual | MethodAttributes.HideBySig, 324                 typeof(bool), new Type[] { typeof(object) }); 325             ILGenerator gen = mb.GetILGenerator(); 326             LocalBuilder other = gen.DeclareLocal(tb); 327             Label next = gen.DefineLabel(); 328             gen.Emit(OpCodes.Ldarg_1); 329             gen.Emit(OpCodes.Isinst, tb); 330             gen.Emit(OpCodes.Stloc, other); 331             gen.Emit(OpCodes.Ldloc, other); 332             gen.Emit(OpCodes.Brtrue_S, next); 333             gen.Emit(OpCodes.Ldc_I4_0); 334             gen.Emit(OpCodes.Ret); 335             gen.MarkLabel(next); 336             foreach (FieldInfo field in fields) { 337                 Type ft = field.FieldType; 338                 Type ct = typeof(EqualityComparer<>).MakeGenericType(ft); 339                 next = gen.DefineLabel(); 340                 gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null); 341                 gen.Emit(OpCodes.Ldarg_0); 342                 gen.Emit(OpCodes.Ldfld, field); 343                 gen.Emit(OpCodes.Ldloc, other); 344                 gen.Emit(OpCodes.Ldfld, field); 345                 gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", new Type[] { ft, ft }), null); 346                 gen.Emit(OpCodes.Brtrue_S, next); 347                 gen.Emit(OpCodes.Ldc_I4_0); 348                 gen.Emit(OpCodes.Ret); 349                 gen.MarkLabel(next); 350             } 351             gen.Emit(OpCodes.Ldc_I4_1); 352             gen.Emit(OpCodes.Ret); 353         } 354  355         void GenerateGetHashCode(TypeBuilder tb, FieldInfo[] fields) { 356             MethodBuilder mb = tb.DefineMethod("GetHashCode", 357                 MethodAttributes.Public | MethodAttributes.ReuseSlot | 358                 MethodAttributes.Virtual | MethodAttributes.HideBySig, 359                 typeof(int), Type.EmptyTypes); 360             ILGenerator gen = mb.GetILGenerator(); 361             gen.Emit(OpCodes.Ldc_I4_0); 362             foreach (FieldInfo field in fields) { 363                 Type ft = field.FieldType; 364                 Type ct = typeof(EqualityComparer<>).MakeGenericType(ft); 365                 gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null); 366                 gen.Emit(OpCodes.Ldarg_0); 367                 gen.Emit(OpCodes.Ldfld, field); 368                 gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", new Type[] { ft }), null); 369                 gen.Emit(OpCodes.Xor); 370             } 371             gen.Emit(OpCodes.Ret); 372         } 373     } 374  375     public sealed class ParseException : Exception 376     { 377         int position; 378  379         public ParseException(string message, int position) 380             : base(message) { 381             this.position = position; 382         } 383  384         public int Position { 385             get { return position; } 386         } 387  388         public override string ToString() { 389             return string.Format(Res.ParseExceptionFormat, Message, position); 390         } 391     } 392  393     internal class ExpressionParser 394     { 395         struct Token 396         { 397             public TokenId id; 398             public string text; 399             public int pos; 400         } 401  402         enum TokenId 403         { 404             Unknown, 405             End, 406             Identifier, 407             StringLiteral, 408             IntegerLiteral, 409             RealLiteral, 410             Exclamation, 411             Percent, 412             Amphersand, 413             OpenParen, 414             CloseParen, 415             Asterisk, 416             Plus, 417             Comma, 418             Minus, 419             Dot, 420             Slash, 421             Colon, 422             LessThan, 423             Equal, 424             GreaterThan, 425             Question, 426             OpenBracket, 427             CloseBracket, 428             Bar, 429             ExclamationEqual, 430             DoubleAmphersand, 431             LessThanEqual, 432             LessGreater, 433             DoubleEqual, 434             GreaterThanEqual, 435             DoubleBar 436         } 437  438         interface ILogicalSignatures 439         { 440             void F(bool x, bool y); 441             void F(bool? x, bool? y); 442         } 443  444         interface IArithmeticSignatures 445         { 446             void F(int x, int y); 447             void F(uint x, uint y); 448             void F(long x, long y); 449             void F(ulong x, ulong y); 450             void F(float x, float y); 451             void F(double x, double y); 452             void F(decimal x, decimal y); 453             void F(int? x, int? y); 454             void F(uint? x, uint? y); 455             void F(long? x, long? y); 456             void F(ulong? x, ulong? y); 457             void F(float? x, float? y); 458             void F(double? x, double? y); 459             void F(decimal? x, decimal? y); 460         } 461  462         interface IRelationalSignatures : IArithmeticSignatures 463         { 464             void F(string x, string y); 465             void F(char x, char y); 466             void F(DateTime x, DateTime y); 467             void F(TimeSpan x, TimeSpan y); 468             void F(char? x, char? y); 469             void F(DateTime? x, DateTime? y); 470             void F(TimeSpan? x, TimeSpan? y); 471         } 472  473         interface IEqualitySignatures : IRelationalSignatures 474         { 475             void F(bool x, bool y); 476             void F(bool? x, bool? y); 477         } 478  479         interface IAddSignatures : IArithmeticSignatures 480         { 481             void F(DateTime x, TimeSpan y); 482             void F(TimeSpan x, TimeSpan y); 483             void F(DateTime? x, TimeSpan? y); 484             void F(TimeSpan? x, TimeSpan? y); 485         } 486  487         interface ISubtractSignatures : IAddSignatures 488         { 489             void F(DateTime x, DateTime y); 490             void F(DateTime? x, DateTime? y); 491         } 492  493         interface INegationSignatures 494         { 495             void F(int x); 496             void F(long x); 497             void F(float x); 498             void F(double x); 499             void F(decimal x); 500             void F(int? x); 501             void F(long? x); 502             void F(float? x); 503             void F(double? x); 504             void F(decimal? x); 505         } 506  507         interface INotSignatures 508         { 509             void F(bool x); 510             void F(bool? x); 511         } 512  513         interface IEnumerableSignatures 514         { 515             void Where(bool predicate); 516             void Any(); 517             void Any(bool predicate); 518             void All(bool predicate); 519             void Count(); 520             void Count(bool predicate); 521             void Min(object selector); 522             void Max(object selector); 523             void Sum(int selector); 524             void Sum(int? selector); 525             void Sum(long selector); 526             void Sum(long? selector); 527             void Sum(float selector); 528             void Sum(float? selector); 529             void Sum(double selector); 530             void Sum(double? selector); 531             void Sum(decimal selector); 532             void Sum(decimal? selector); 533             void Average(int selector); 534             void Average(int? selector); 535             void Average(long selector); 536             void Average(long? selector); 537             void Average(float selector); 538             void Average(float? selector); 539             void Average(double selector); 540             void Average(double? selector); 541             void Average(decimal selector); 542             void Average(decimal? selector); 543         } 544  545         static readonly Type[] predefinedTypes = { 546             typeof(Object), 547             typeof(Boolean), 548             typeof(Char), 549             typeof(String), 550             typeof(SByte), 551             typeof(Byte), 552             typeof(Int16), 553             typeof(UInt16), 554             typeof(Int32), 555             typeof(UInt32), 556             typeof(Int64), 557             typeof(UInt64), 558             typeof(Single), 559             typeof(Double), 560             typeof(Decimal), 561             typeof(DateTime), 562             typeof(TimeSpan), 563             typeof(Guid), 564             typeof(Math), 565             typeof(Convert) 566         }; 567  568         static readonly Expression trueLiteral = Expression.Constant(true); 569         static readonly Expression falseLiteral = Expression.Constant(false); 570         static readonly Expression nullLiteral = Expression.Constant(null); 571  572         static readonly string keywordIt = "it"; 573         static readonly string keywordIif = "iif"; 574         static readonly string keywordNew = "new"; 575  576         static Dictionary<string, object> keywords; 577  578         Dictionary<string, object> symbols; 579         IDictionary<string, object> externals; 580         Dictionary<Expression, string> literals; 581         ParameterExpression it; 582         string text; 583         int textPos; 584         int textLen; 585         char ch; 586         Token token; 587  588         public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values) { 589             if (expression == null) throw new ArgumentNullException("expression"); 590             if (keywords == null) keywords = CreateKeywords(); 591             symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); 592             literals = new Dictionary<Expression, string>(); 593             if (parameters != null) ProcessParameters(parameters); 594             if (values != null) ProcessValues(values); 595             text = expression; 596             textLen = text.Length; 597             SetTextPos(0); 598             NextToken(); 599         } 600  601         void ProcessParameters(ParameterExpression[] parameters) { 602             foreach (ParameterExpression pe in parameters) 603                 if (!String.IsNullOrEmpty(pe.Name)) 604                     AddSymbol(pe.Name, pe); 605             if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name)) 606                 it = parameters[0]; 607         } 608  609         void ProcessValues(object[] values) { 610             for (int i = 0; i < values.Length; i++) { 611                 object value = values[i]; 612                 if (i == values.Length - 1 && value is IDictionary<string, object>) { 613                     externals = (IDictionary<string, object>)value; 614                 } 615                 else { 616                     AddSymbol("@" + i.ToString(System.Globalization.CultureInfo.InvariantCulture), value); 617                 } 618             } 619         } 620  621         void AddSymbol(string name, object value) { 622             if (symbols.ContainsKey(name)) 623                 throw ParseError(Res.DuplicateIdentifier, name); 624             symbols.Add(name, value); 625         } 626  627         public Expression Parse(Type resultType) { 628             int exprPos = token.pos; 629             Expression expr = ParseExpression(); 630             if (resultType != null) 631                 if ((expr = PromoteExpression(expr, resultType, true)) == null) 632                     throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType)); 633             ValidateToken(TokenId.End, Res.SyntaxError); 634             return expr; 635         } 636  637 #pragma warning disable 0219 638         public IEnumerable<DynamicOrdering> ParseOrdering() { 639             List<DynamicOrdering> orderings = new List<DynamicOrdering>(); 640             while (true) { 641                 Expression expr = ParseExpression(); 642                 bool ascending = true; 643                 if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending")) { 644                     NextToken(); 645                 } 646                 else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending")) { 647                     NextToken(); 648                     ascending = false; 649                 } 650                 orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending }); 651                 if (token.id != TokenId.Comma) break; 652                 NextToken(); 653             } 654             ValidateToken(TokenId.End, Res.SyntaxError); 655             return orderings; 656         } 657 #pragma warning restore 0219 658  659         // ?: operator 660         Expression ParseExpression() { 661             int errorPos = token.pos; 662             Expression expr = ParseLogicalOr(); 663             if (token.id == TokenId.Question) { 664                 NextToken(); 665                 Expression expr1 = ParseExpression(); 666                 ValidateToken(TokenId.Colon, Res.ColonExpected); 667                 NextToken(); 668                 Expression expr2 = ParseExpression(); 669                 expr = GenerateConditional(expr, expr1, expr2, errorPos); 670             } 671             return expr; 672         } 673  674         // ||, or operator 675         Expression ParseLogicalOr() { 676             Expression left = ParseLogicalAnd(); 677             while (token.id == TokenId.DoubleBar || TokenIdentifierIs("or")) { 678                 Token op = token; 679                 NextToken(); 680                 Expression right = ParseLogicalAnd(); 681                 CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos); 682                 left = Expression.OrElse(left, right); 683             } 684             return left; 685         } 686  687         // &&, and operator 688         Expression ParseLogicalAnd() { 689             Expression left = ParseComparison(); 690             while (token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and")) { 691                 Token op = token; 692                 NextToken(); 693                 Expression right = ParseComparison(); 694                 CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos); 695                 left = Expression.AndAlso(left, right); 696             } 697             return left; 698         } 699  700         // =, ==, !=, <>, >, >=, <, <= operators 701         Expression ParseComparison() { 702             Expression left = ParseAdditive(); 703             while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual || 704                 token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater || 705                 token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual || 706                 token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual) { 707                 Token op = token; 708                 NextToken(); 709                 Expression right = ParseAdditive(); 710                 bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual || 711                     op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater; 712                 if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType) { 713                     if (left.Type != right.Type) { 714                         if (left.Type.IsAssignableFrom(right.Type)) { 715                             right = Expression.Convert(right, left.Type); 716                         } 717                         else if (right.Type.IsAssignableFrom(left.Type)) { 718                             left = Expression.Convert(left, right.Type); 719                         } 720                         else { 721                             throw IncompatibleOperandsError(op.text, left, right, op.pos); 722                         } 723                     } 724                 } 725                 else if (IsEnumType(left.Type) || IsEnumType(right.Type)) { 726                     if (left.Type != right.Type) { 727                         Expression e; 728                         if ((e = PromoteExpression(right, left.Type, true)) != null) { 729                             right = e; 730                         } 731                         else if ((e = PromoteExpression(left, right.Type, true)) != null) { 732                             left = e; 733                         } 734                         else { 735                             throw IncompatibleOperandsError(op.text, left, right, op.pos); 736                         } 737                     } 738                 } 739                 else { 740                     CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), 741                         op.text, ref left, ref right, op.pos); 742                 } 743                 switch (op.id) { 744                     case TokenId.Equal: 745                     case TokenId.DoubleEqual: 746                         left = GenerateEqual(left, right); 747                         break; 748                     case TokenId.ExclamationEqual: 749                     case TokenId.LessGreater: 750                         left = GenerateNotEqual(left, right); 751                         break; 752                     case TokenId.GreaterThan: 753                         left = GenerateGreaterThan(left, right); 754                         break; 755                     case TokenId.GreaterThanEqual: 756                         left = GenerateGreaterThanEqual(left, right); 757                         break; 758                     case TokenId.LessThan: 759                         left = GenerateLessThan(left, right); 760                         break; 761                     case TokenId.LessThanEqual: 762                         left = GenerateLessThanEqual(left, right); 763                         break; 764                 } 765             } 766             return left; 767         } 768  769         // +, -, & operators 770         Expression ParseAdditive() { 771             Expression left = ParseMultiplicative(); 772             while (token.id == TokenId.Plus || token.id == TokenId.Minus || 773                 token.id == TokenId.Amphersand) { 774                 Token op = token; 775                 NextToken(); 776                 Expression right = ParseMultiplicative(); 777                 switch (op.id) { 778                     case TokenId.Plus: 779                         if (left.Type == typeof(string) || right.Type == typeof(string)) 780                             goto case TokenId.Amphersand; 781                         CheckAndPromoteOperands(typeof(IAddSignatures), op.text, ref left, ref right, op.pos); 782                         left = GenerateAdd(left, right); 783                         break; 784                     case TokenId.Minus: 785                         CheckAndPromoteOperands(typeof(ISubtractSignatures), op.text, ref left, ref right, op.pos); 786                         left = GenerateSubtract(left, right); 787                         break; 788                     case TokenId.Amphersand: 789                         left = GenerateStringConcat(left, right); 790                         break; 791                 } 792             } 793             return left; 794         } 795  796         // *, /, %, mod operators 797         Expression ParseMultiplicative() { 798             Expression left = ParseUnary(); 799             while (token.id == TokenId.Asterisk || token.id == TokenId.Slash || 800                 token.id == TokenId.Percent || TokenIdentifierIs("mod")) { 801                 Token op = token; 802                 NextToken(); 803                 Expression right = ParseUnary(); 804                 CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.text, ref left, ref right, op.pos); 805                 switch (op.id) { 806                     case TokenId.Asterisk: 807                         left = Expression.Multiply(left, right); 808                         break; 809                     case TokenId.Slash: 810                         left = Expression.Divide(left, right); 811                         break; 812                     case TokenId.Percent: 813                     case TokenId.Identifier: 814                         left = Expression.Modulo(left, right); 815                         break; 816                 } 817             } 818             return left; 819         } 820  821         // -, !, not unary operators 822         Expression ParseUnary() { 823             if (token.id == TokenId.Minus || token.id == TokenId.Exclamation || 824                 TokenIdentifierIs("not")) { 825                 Token op = token; 826                 NextToken(); 827                 if (op.id == TokenId.Minus && (token.id == TokenId.IntegerLiteral || 828                     token.id == TokenId.RealLiteral)) { 829                     token.text = "-" + token.text; 830                     token.pos = op.pos; 831                     return ParsePrimary(); 832                 } 833                 Expression expr = ParseUnary(); 834                 if (op.id == TokenId.Minus) { 835                     CheckAndPromoteOperand(typeof(INegationSignatures), op.text, ref expr, op.pos); 836                     expr = Expression.Negate(expr); 837                 } 838                 else { 839                     CheckAndPromoteOperand(typeof(INotSignatures), op.text, ref expr, op.pos); 840                     expr = Expression.Not(expr); 841                 } 842                 return expr; 843             } 844             return ParsePrimary(); 845         } 846  847         Expression ParsePrimary() { 848             Expression expr = ParsePrimaryStart(); 849             while (true) { 850                 if (token.id == TokenId.Dot) { 851                     NextToken(); 852                     expr = ParseMemberAccess(null, expr); 853                 } 854                 else if (token.id == TokenId.OpenBracket) { 855                     expr = ParseElementAccess(expr); 856                 } 857                 else { 858                     break; 859                 } 860             } 861             return expr; 862         } 863  864         Expression ParsePrimaryStart() { 865             switch (token.id) { 866                 case TokenId.Identifier: 867                     return ParseIdentifier(); 868                 case TokenId.StringLiteral: 869                     return ParseStringLiteral(); 870                 case TokenId.IntegerLiteral: 871                     return ParseIntegerLiteral(); 872                 case TokenId.RealLiteral: 873                     return ParseRealLiteral(); 874                 case TokenId.OpenParen: 875                     return ParseParenExpression(); 876                 default: 877                     throw ParseError(Res.ExpressionExpected); 878             } 879         } 880  881         Expression ParseStringLiteral() { 882             ValidateToken(TokenId.StringLiteral); 883             char quote = token.text[0]; 884             string s = token.text.Substring(1, token.text.Length - 2); 885             int start = 0; 886             while (true) { 887                 int i = s.IndexOf(quote, start); 888                 if (i < 0) break; 889                 s = s.Remove(i, 1); 890                 start = i + 1; 891             } 892             if (quote == '\'') { 893                 if (s.Length != 1) 894                     throw ParseError(Res.InvalidCharacterLiteral); 895                 NextToken(); 896                 return CreateLiteral(s[0], s); 897             } 898             NextToken(); 899             return CreateLiteral(s, s); 900         } 901  902         Expression ParseIntegerLiteral() { 903             ValidateToken(TokenId.IntegerLiteral); 904             string text = token.text; 905             if (text[0] != '-') { 906                 ulong value; 907                 if (!UInt64.TryParse(text, out value)) 908                     throw ParseError(Res.InvalidIntegerLiteral, text); 909                 NextToken(); 910                 if (value <= (ulong)Int32.MaxValue) return CreateLiteral((int)value, text); 911                 if (value <= (ulong)UInt32.MaxValue) return CreateLiteral((uint)value, text); 912                 if (value <= (ulong)Int64.MaxValue) return CreateLiteral((long)value, text); 913                 return CreateLiteral(value, text); 914             } 915             else { 916                 long value; 917                 if (!Int64.TryParse(text, out value)) 918                     throw ParseError(Res.InvalidIntegerLiteral, text); 919                 NextToken(); 920                 if (value >= Int32.MinValue && value <= Int32.MaxValue) 921                     return CreateLiteral((int)value, text); 922                 return CreateLiteral(value, text); 923             } 924         } 925  926         Expression ParseRealLiteral() { 927             ValidateToken(TokenId.RealLiteral); 928             string text = token.text; 929             object value = null; 930             char last = text[text.Length - 1]; 931             if (last == 'F' || last == 'f') { 932                 float f; 933                 if (Single.TryParse(text.Substring(0, text.Length - 1), out f)) value = f; 934             } 935             else { 936                 double d; 937                 if (Double.TryParse(text, out d)) value = d; 938             } 939             if (value == null) throw ParseError(Res.InvalidRealLiteral, text); 940             NextToken(); 941             return CreateLiteral(value, text); 942         } 943  944         Expression CreateLiteral(object value, string text) { 945             ConstantExpression expr = Expression.Constant(value); 946             literals.Add(expr, text); 947             return expr; 948         } 949  950         Expression ParseParenExpression() { 951             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected); 952             NextToken(); 953             Expression e = ParseExpression(); 954             ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected); 955             NextToken(); 956             return e; 957         } 958  959         Expression ParseIdentifier() { 960             ValidateToken(TokenId.Identifier); 961             object value; 962             if (keywords.TryGetValue(token.text, out value)) { 963                 if (value is Type) return ParseTypeAccess((Type)value); 964                 if (value == (object)keywordIt) return ParseIt(); 965                 if (value == (object)keywordIif) return ParseIif(); 966                 if (value == (object)keywordNew) return ParseNew(); 967                 NextToken(); 968                 return (Expression)value; 969             } 970             if (symbols.TryGetValue(token.text, out value) || 971                 externals != null && externals.TryGetValue(token.text, out value)) { 972                 Expression expr = value as Expression; 973                 if (expr == null) { 974                     expr = Expression.Constant(value); 975                 } 976                 else { 977                     LambdaExpression lambda = expr as LambdaExpression; 978                     if (lambda != null) return ParseLambdaInvocation(lambda); 979                 } 980                 NextToken(); 981                 return expr; 982             } 983             if (it != null) return ParseMemberAccess(null, it); 984             throw ParseError(Res.UnknownIdentifier, token.text); 985         } 986  987         Expression ParseIt() { 988             if (it == null) 989                 throw ParseError(Res.NoItInScope); 990             NextToken(); 991             return it; 992         } 993  994         Expression ParseIif() { 995             int errorPos = token.pos; 996             NextToken(); 997             Expression[] args = ParseArgumentList(); 998             if (args.Length != 3) 999                 throw ParseError(errorPos, Res.IifRequiresThreeArgs);1000             return GenerateConditional(args[0], args[1], args[2], errorPos);1001         }1002 1003         Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos) {1004             if (test.Type != typeof(bool))1005                 throw ParseError(errorPos, Res.FirstExprMustBeBool);1006             if (expr1.Type != expr2.Type) {1007                 Expression expr1as2 = expr2 != nullLiteral ? PromoteExpression(expr1, expr2.Type, true) : null;1008                 Expression expr2as1 = expr1 != nullLiteral ? PromoteExpression(expr2, expr1.Type, true) : null;1009                 if (expr1as2 != null && expr2as1 == null) {1010                     expr1 = expr1as2;1011                 }1012                 else if (expr2as1 != null && expr1as2 == null) {1013                     expr2 = expr2as1;1014                 }1015                 else {1016                     string type1 = expr1 != nullLiteral ? expr1.Type.Name : "null";1017                     string type2 = expr2 != nullLiteral ? expr2.Type.Name : "null";1018                     if (expr1as2 != null && expr2as1 != null)1019                         throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);1020                     throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);1021                 }1022             }1023             return Expression.Condition(test, expr1, expr2);1024         }1025 1026         Expression ParseNew() {1027             NextToken();1028             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);1029             NextToken();1030             List<DynamicProperty> properties = new List<DynamicProperty>();1031             List<Expression> expressions = new List<Expression>();1032             while (true) {1033                 int exprPos = token.pos;1034                 Expression expr = ParseExpression();1035                 string propName;1036                 if (TokenIdentifierIs("as")) {1037                     NextToken();1038                     propName = GetIdentifier();1039                     NextToken();1040                 }1041                 else {1042                     MemberExpression me = expr as MemberExpression;1043                     if (me == null) throw ParseError(exprPos, Res.MissingAsClause);1044                     propName = me.Member.Name;1045                 }1046                 expressions.Add(expr);1047                 properties.Add(new DynamicProperty(propName, expr.Type));1048                 if (token.id != TokenId.Comma) break;1049                 NextToken();1050             }1051             ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);1052             NextToken();1053             Type type = DynamicExpression.CreateClass(properties);1054             MemberBinding[] bindings = new MemberBinding[properties.Count];1055             for (int i = 0; i < bindings.Length; i++)1056                 bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);1057             return Expression.MemberInit(Expression.New(type), bindings);1058         }1059 1060         Expression ParseLambdaInvocation(LambdaExpression lambda) {1061             int errorPos = token.pos;1062             NextToken();1063             Expression[] args = ParseArgumentList();1064             MethodBase method;1065             if (FindMethod(lambda.Type, "Invoke", false, args, out method) != 1)1066                 throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);1067             return Expression.Invoke(lambda, args);1068         }1069 1070         Expression ParseTypeAccess(Type type) {1071             int errorPos = token.pos;1072             NextToken();1073             if (token.id == TokenId.Question) {1074                 if (!type.IsValueType || IsNullableType(type))1075                     throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type));1076                 type = typeof(Nullable<>).MakeGenericType(type);1077                 NextToken();1078             }1079             if (token.id == TokenId.OpenParen) {1080                 Expression[] args = ParseArgumentList();1081                 MethodBase method;1082                 switch (FindBestMethod(type.GetConstructors(), args, out method)) {1083                     case 0:1084                         if (args.Length == 1)1085                             return GenerateConversion(args[0], type, errorPos);1086                         throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type));1087                     case 1:1088                         return Expression.New((ConstructorInfo)method, args);1089                     default:1090                         throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type));1091                 }1092             }1093             ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected);1094             NextToken();1095             return ParseMemberAccess(type, null);1096         }1097 1098         Expression GenerateConversion(Expression expr, Type type, int errorPos) {1099             Type exprType = expr.Type;1100             if (exprType == type) return expr;1101             if (exprType.IsValueType && type.IsValueType) {1102                 if ((IsNullableType(exprType) || IsNullableType(type)) &&1103                     GetNonNullableType(exprType) == GetNonNullableType(type))1104                     return Expression.Convert(expr, type);1105                 if ((IsNumericType(exprType) || IsEnumType(exprType)) &&1106                     (IsNumericType(type)) || IsEnumType(type))1107                     return Expression.ConvertChecked(expr, type);1108             }1109             if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) ||1110                 exprType.IsInterface || type.IsInterface)1111                 return Expression.Convert(expr, type);1112             throw ParseError(errorPos, Res.CannotConvertValue,1113                 GetTypeName(exprType), GetTypeName(type));1114         }1115 1116         Expression ParseMemberAccess(Type type, Expression instance) {1117             if (instance != null) type = instance.Type;1118             int errorPos = token.pos;1119             string id = GetIdentifier();1120             NextToken();1121             if (token.id == TokenId.OpenParen) {1122                 if (instance != null && type != typeof(string)) {1123                     Type enumerableType = FindGenericType(typeof(IEnumerable<>), type);1124                     if (enumerableType != null) {1125                         Type elementType = enumerableType.GetGenericArguments()[0];1126                         return ParseAggregate(instance, elementType, id, errorPos);1127                     }1128                 }1129                 Expression[] args = ParseArgumentList();1130                 MethodBase mb;1131                 switch (FindMethod(type, id, instance == null, args, out mb)) {1132                     case 0:1133                         throw ParseError(errorPos, Res.NoApplicableMethod,1134                             id, GetTypeName(type));1135                     case 1:1136                         MethodInfo method = (MethodInfo)mb;1137                         if (!IsPredefinedType(method.DeclaringType))1138                             throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType));1139                         if (method.ReturnType == typeof(void))1140                             throw ParseError(errorPos, Res.MethodIsVoid,1141                                 id, GetTypeName(method.DeclaringType));1142                         return Expression.Call(instance, (MethodInfo)method, args);1143                     default:1144                         throw ParseError(errorPos, Res.AmbiguousMethodInvocation,1145                             id, GetTypeName(type));1146                 }1147             }1148             else {1149                 MemberInfo member = FindPropertyOrField(type, id, instance == null);1150                 if (member == null)1151                     throw ParseError(errorPos, Res.UnknownPropertyOrField,1152                         id, GetTypeName(type));1153                 return member is PropertyInfo ?1154                     Expression.Property(instance, (PropertyInfo)member) :1155                     Expression.Field(instance, (FieldInfo)member);1156             }1157         }1158 1159         static Type FindGenericType(Type generic, Type type) {1160             while (type != null && type != typeof(object)) {1161                 if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) return type;1162                 if (generic.IsInterface) {1163                     foreach (Type intfType in type.GetInterfaces()) {1164                         Type found = FindGenericType(generic, intfType);1165                         if (found != null) return found;1166                     }1167                 }1168                 type = type.BaseType;1169             }1170             return null;1171         }1172 1173         Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) {1174             ParameterExpression outerIt = it;1175             ParameterExpression innerIt = Expression.Parameter(elementType, "");1176             it = innerIt;1177             Expression[] args = ParseArgumentList();1178             it = outerIt;1179             MethodBase signature;1180             if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)1181                 throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);1182             Type[] typeArgs;1183             if (signature.Name == "Min" || signature.Name == "Max") {1184                 typeArgs = new Type[] { elementType, args[0].Type };1185             }1186             else {1187                 typeArgs = new Type[] { elementType };1188             }1189             if (args.Length == 0) {1190                 args = new Expression[] { instance };1191             }1192             else {1193                 args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };1194             }1195             return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args);1196         }1197 1198         Expression[] ParseArgumentList() {1199             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);1200             NextToken();1201             Expression[] args = token.id != TokenId.CloseParen ? ParseArguments() : new Expression[0];1202             ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);1203             NextToken();1204             return args;1205         }1206 1207         Expression[] ParseArguments() {1208             List<Expression> argList = new List<Expression>();1209             while (true) {1210                 argList.Add(ParseExpression());1211                 if (token.id != TokenId.Comma) break;1212                 NextToken();1213             }1214             return argList.ToArray();1215         }1216 1217         Expression ParseElementAccess(Expression expr) {1218             int errorPos = token.pos;1219             ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected);1220             NextToken();1221             Expression[] args = ParseArguments();1222             ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected);1223             NextToken();1224             if (expr.Type.IsArray) {1225                 if (expr.Type.GetArrayRank() != 1 || args.Length != 1)1226                     throw ParseError(errorPos, Res.CannotIndexMultiDimArray);1227                 Expression index = PromoteExpression(args[0], typeof(int), true);1228                 if (index == null)1229                     throw ParseError(errorPos, Res.InvalidIndex);1230                 return Expression.ArrayIndex(expr, index);1231             }1232             else {1233                 MethodBase mb;1234                 switch (FindIndexer(expr.Type, args, out mb)) {1235                     case 0:1236                         throw ParseError(errorPos, Res.NoApplicableIndexer,1237                             GetTypeName(expr.Type));1238                     case 1:1239                         return Expression.Call(expr, (MethodInfo)mb, args);1240                     default:1241                         throw ParseError(errorPos, Res.AmbiguousIndexerInvocation,1242                             GetTypeName(expr.Type));1243                 }1244             }1245         }1246 1247         static bool IsPredefinedType(Type type) {1248             foreach (Type t in predefinedTypes) if (t == type) return true;1249             return false;1250         }1251 1252         static bool IsNullableType(Type type) {1253             return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);1254         }1255 1256         static Type GetNonNullableType(Type type) {1257             return IsNullableType(type) ? type.GetGenericArguments()[0] : type;1258         }1259 1260         static string GetTypeName(Type type) {1261             Type baseType = GetNonNullableType(type);1262             string s = baseType.Name;1263             if (type != baseType) s += '?';1264             return s;1265         }1266 1267         static bool IsNumericType(Type type) {1268             return GetNumericTypeKind(type) != 0;1269         }1270 1271         static bool IsSignedIntegralType(Type type) {1272             return GetNumericTypeKind(type) == 2;1273         }1274 1275         static bool IsUnsignedIntegralType(Type type) {1276             return GetNumericTypeKind(type) == 3;1277         }1278 1279         static int GetNumericTypeKind(Type type) {1280             type = GetNonNullableType(type);1281             if (type.IsEnum) return 0;1282             switch (Type.GetTypeCode(type)) {1283                 case TypeCode.Char:1284                 case TypeCode.Single:1285                 case TypeCode.Double:1286                 case TypeCode.Decimal:1287                     return 1;1288                 case TypeCode.SByte:1289                 case TypeCode.Int16:1290                 case TypeCode.Int32:1291                 case TypeCode.Int64:1292                     return 2;1293                 case TypeCode.Byte:1294                 case TypeCode.UInt16:1295                 case TypeCode.UInt32:1296                 case TypeCode.UInt64:1297                     return 3;1298                 default:1299                     return 0;1300             }1301         }1302 1303         static bool IsEnumType(Type type) {1304             return GetNonNullableType(type).IsEnum;1305         }1306 1307         void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos) {1308             Expression[] args = new Expression[] { expr };1309             MethodBase method;1310             if (FindMethod(signatures, "F", false, args, out method) != 1)1311                 throw ParseError(errorPos, Res.IncompatibleOperand,1312                     opName, GetTypeName(args[0].Type));1313             expr = args[0];1314         }1315 1316         void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos) {1317             Expression[] args = new Expression[] { left, right };1318             MethodBase method;1319             if (FindMethod(signatures, "F", false, args, out method) != 1)1320                 throw IncompatibleOperandsError(opName, left, right, errorPos);1321             left = args[0];1322             right = args[1];1323         }1324 1325         Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos) {1326             return ParseError(pos, Res.IncompatibleOperands,1327                 opName, GetTypeName(left.Type), GetTypeName(right.Type));1328         }1329 1330         MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess) {1331             BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |1332                 (staticAccess ? BindingFlags.Static : BindingFlags.Instance);1333             foreach (Type t in SelfAndBaseTypes(type)) {1334                 MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field,1335                     flags, Type.FilterNameIgnoreCase, memberName);1336                 if (members.Length != 0) return members[0];1337             }1338             return null;1339         }1340 1341         int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method) {1342             BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |1343                 (staticAccess ? BindingFlags.Static : BindingFlags.Instance);1344             foreach (Type t in SelfAndBaseTypes(type)) {1345                 MemberInfo[] members = t.FindMembers(MemberTypes.Method,1346                     flags, Type.FilterNameIgnoreCase, methodName);1347                 int count = FindBestMethod(members.Cast<MethodBase>(), args, out method);1348                 if (count != 0) return count;1349             }1350             method = null;1351             return 0;1352         }1353 1354         int FindIndexer(Type type, Expression[] args, out MethodBase method) {1355             foreach (Type t in SelfAndBaseTypes(type)) {1356                 MemberInfo[] members = t.GetDefaultMembers();1357                 if (members.Length != 0) {1358                     IEnumerable<MethodBase> methods = members.1359                         OfType<PropertyInfo>().1360                         Select(p => (MethodBase)p.GetGetMethod()).1361                         Where(m => m != null);1362                     int count = FindBestMethod(methods, args, out method);1363                     if (count != 0) return count;1364                 }1365             }1366             method = null;1367             return 0;1368         }1369 1370         static IEnumerable<Type> SelfAndBaseTypes(Type type) {1371             if (type.IsInterface) {1372                 List<Type> types = new List<Type>();1373                 AddInterface(types, type);1374                 return types;1375             }1376             return SelfAndBaseClasses(type);1377         }1378 1379         static IEnumerable<Type> SelfAndBaseClasses(Type type) {1380             while (type != null) {1381                 yield return type;1382                 type = type.BaseType;1383             }1384         }1385 1386         static void AddInterface(List<Type> types, Type type) {1387             if (!types.Contains(type)) {1388                 types.Add(type);1389                 foreach (Type t in type.GetInterfaces()) AddInterface(types, t);1390             }1391         }1392 1393         class MethodData1394         {1395             public MethodBase MethodBase;1396             public ParameterInfo[] Parameters;1397             public Expression[] Args;1398         }1399 1400         int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method) {1401             MethodData[] applicable = methods.1402                 Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }).1403                 Where(m => IsApplicable(m, args)).1404                 ToArray();1405             if (applicable.Length > 1) {1406                 applicable = applicable.1407                     Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))).1408                     ToArray();1409             }1410             if (applicable.Length == 1) {1411                 MethodData md = applicable[0];1412                 for (int i = 0; i < args.Length; i++) args[i] = md.Args[i];1413                 method = md.MethodBase;1414             }1415             else {1416                 method = null;1417             }1418             return applicable.Length;1419         }1420 1421         bool IsApplicable(MethodData method, Expression[] args) {1422             if (method.Parameters.Length != args.Length) return false;1423             Expression[] promotedArgs = new Expression[args.Length];1424             for (int i = 0; i < args.Length; i++) {1425                 ParameterInfo pi = method.Parameters[i];1426                 if (pi.IsOut) return false;1427                 Expression promoted = PromoteExpression(args[i], pi.ParameterType, false);1428                 if (promoted == null) return false;1429                 promotedArgs[i] = promoted;1430             }1431             method.Args = promotedArgs;1432             return true;1433         }1434 1435         Expression PromoteExpression(Expression expr, Type type, bool exact) {1436             if (expr.Type == type) return expr;1437             if (expr is ConstantExpression) {1438                 ConstantExpression ce = (ConstantExpression)expr;1439                 if (ce == nullLiteral) {1440                     if (!type.IsValueType || IsNullableType(type))1441                         return Expression.Constant(null, type);1442                 }1443                 else {1444                     string text;1445                     if (literals.TryGetValue(ce, out text)) {1446                         Type target = GetNonNullableType(type);1447                         Object value = null;1448                         switch (Type.GetTypeCode(ce.Type)) {1449                             case TypeCode.Int32:1450                             case TypeCode.UInt32:1451                             case TypeCode.Int64:1452                             case TypeCode.UInt64:1453                                 value = ParseNumber(text, target);1454                                 break;1455                             case TypeCode.Double:1456                                 if (target == typeof(decimal)) value = ParseNumber(text, target);1457                                 break;1458                             case TypeCode.String:1459                                 value = ParseEnum(text, target);1460                                 break;1461                         }1462                         if (value != null)1463                             return Expression.Constant(value, type);1464                     }1465                 }1466             }1467             if (IsCompatibleWith(expr.Type, type)) {1468                 if (type.IsValueType || exact) return Expression.Convert(expr, type);1469                 return expr;1470             }1471             return null;1472         }1473 1474         static object ParseNumber(string text, Type type) {1475             switch (Type.GetTypeCode(GetNonNullableType(type))) {1476                 case TypeCode.SByte:1477                     sbyte sb;1478                     if (sbyte.TryParse(text, out sb)) return sb;1479                     break;1480                 case TypeCode.Byte:1481                     byte b;1482                     if (byte.TryParse(text, out b)) return b;1483                     break;1484                 case TypeCode.Int16:1485                     short s;1486                     if (short.TryParse(text, out s)) return s;1487                     break;1488                 case TypeCode.UInt16:1489                     ushort us;1490                     if (ushort.TryParse(text, out us)) return us;1491                     break;1492                 case TypeCode.Int32:1493                     int i;1494                     if (int.TryParse(text, out i)) return i;1495                     break;1496                 case TypeCode.UInt32:1497                     uint ui;1498                     if (uint.TryParse(text, out ui)) return ui;1499                     break;1500                 case TypeCode.Int64:1501                     long l;1502                     if (long.TryParse(text, out l)) return l;1503                     break;1504                 case TypeCode.UInt64:1505                     ulong ul;1506                     if (ulong.TryParse(text, out ul)) return ul;1507                     break;1508                 case TypeCode.Single:1509                     float f;1510                     if (float.TryParse(text, out f)) return f;1511                     break;1512                 case TypeCode.Double:1513                     double d;1514                     if (double.TryParse(text, out d)) return d;1515                     break;1516                 case TypeCode.Decimal:1517                     decimal e;1518                     if (decimal.TryParse(text, out e)) return e;1519                     break;1520             }1521             return null;1522         }1523 1524         static object ParseEnum(string name, Type type) {1525             if (type.IsEnum) {1526                 MemberInfo[] memberInfos = type.FindMembers(MemberTypes.Field,1527                     BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static,1528                     Type.FilterNameIgnoreCase, name);1529                 if (memberInfos.Length != 0) return ((FieldInfo)memberInfos[0]).GetValue(null);1530             }1531             return null;1532         }1533 1534         static bool IsCompatibleWith(Type source, Type target) {1535             if (source == target) return true;1536             if (!target.IsValueType) return target.IsAssignableFrom(source);1537             Type st = GetNonNullableType(source);1538             Type tt = GetNonNullableType(target);1539             if (st != source && tt == target) return false;1540             TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st);1541             TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);1542             switch (sc) {1543                 case TypeCode.SByte:1544                     switch (tc) {1545                         case TypeCode.SByte:1546                         case TypeCode.Int16:1547                         case TypeCode.Int32:1548                         case TypeCode.Int64:1549                         case TypeCode.Single:1550                         case TypeCode.Double:1551                         case TypeCode.Decimal:1552                             return true;1553                     }1554                     break;1555                 case TypeCode.Byte:1556                     switch (tc) {1557                         case TypeCode.Byte:1558                         case TypeCode.Int16:1559                         case TypeCode.UInt16:1560                         case TypeCode.Int32:1561                         case TypeCode.UInt32:1562                         case TypeCode.Int64:1563                         case TypeCode.UInt64:1564                         case TypeCode.Single:1565                         case TypeCode.Double:1566                         case TypeCode.Decimal:1567                             return true;1568                     }1569                     break;1570                 case TypeCode.Int16:1571                     switch (tc) {1572                         case TypeCode.Int16:1573                         case TypeCode.Int32:1574                         case TypeCode.Int64:1575                         case TypeCode.Single:1576                         case TypeCode.Double:1577                         case TypeCode.Decimal:1578                             return true;1579                     }1580                     break;1581                 case TypeCode.UInt16:1582                     switch (tc) {1583                         case TypeCode.UInt16:1584                         case TypeCode.Int32:1585                         case TypeCode.UInt32:1586                         case TypeCode.Int64:1587                         case TypeCode.UInt64:1588                         case TypeCode.Single:1589                         case TypeCode.Double:1590                         case TypeCode.Decimal:1591                             return true;1592                     }1593                     break;1594                 case TypeCode.Int32:1595                     switch (tc) {1596                         case TypeCode.Int32:1597                         case TypeCode.Int64:1598                         case TypeCode.Single:1599                         case TypeCode.Double:1600                         case TypeCode.Decimal:1601                             return true;1602                     }1603                     break;1604                 case TypeCode.UInt32:1605                     switch (tc) {1606                         case TypeCode.UInt32:1607                         case TypeCode.Int64:1608                         case TypeCode.UInt64:1609                         case TypeCode.Single:1610                         case TypeCode.Double:1611                         case TypeCode.Decimal:1612                             return true;1613                     }1614                     break;1615                 case TypeCode.Int64:1616                     switch (tc) {1617                         case TypeCode.Int64:1618                         case TypeCode.Single:1619                         case TypeCode.Double:1620                         case TypeCode.Decimal:1621                             return true;1622                     }1623                     break;1624                 case TypeCode.UInt64:1625                     switch (tc) {1626                         case TypeCode.UInt64:1627                         case TypeCode.Single:1628                         case TypeCode.Double:1629                         case TypeCode.Decimal:1630                             return true;1631                     }1632                     break;1633                 case TypeCode.Single:1634                     switch (tc) {1635                         case TypeCode.Single:1636                         case TypeCode.Double:1637                             return true;1638                     }1639                     break;1640                 default:1641                     if (st == tt) return true;1642                     break;1643             }1644             return false;1645         }1646 1647         static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2) {1648             bool better = false;1649             for (int i = 0; i < args.Length; i++) {1650                 int c = CompareConversions(args[i].Type,1651                     m1.Parameters[i].ParameterType,1652                     m2.Parameters[i].ParameterType);1653                 if (c < 0) return false;1654                 if (c > 0) better = true;1655             }1656             return better;1657         }1658 1659         // Return 1 if s -> t1 is a better conversion than s -> t21660         // Return -1 if s -> t2 is a better conversion than s -> t11661         // Return 0 if neither conversion is better1662         static int CompareConversions(Type s, Type t1, Type t2) {1663             if (t1 == t2) return 0;1664             if (s == t1) return 1;1665             if (s == t2) return -1;1666             bool t1t2 = IsCompatibleWith(t1, t2);1667             bool t2t1 = IsCompatibleWith(t2, t1);1668             if (t1t2 && !t2t1) return 1;1669             if (t2t1 && !t1t2) return -1;1670             if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) return 1;1671             if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) return -1;1672             return 0;1673         }1674 1675         Expression GenerateEqual(Expression left, Expression right) {1676             return Expression.Equal(left, right);1677         }1678 1679         Expression GenerateNotEqual(Expression left, Expression right) {1680             return Expression.NotEqual(left, right);1681         }1682 1683         Expression GenerateGreaterThan(Expression left, Expression right) {1684             if (left.Type == typeof(string)) {1685                 return Expression.GreaterThan(1686                     GenerateStaticMethodCall("Compare", left, right),1687                     Expression.Constant(0)1688                 );1689             }1690             return Expression.GreaterThan(left, right);1691         }1692 1693         Expression GenerateGreaterThanEqual(Expression left, Expression right) {1694             if (left.Type == typeof(string)) {1695                 return Expression.GreaterThanOrEqual(1696                     GenerateStaticMethodCall("Compare", left, right),1697                     Expression.Constant(0)1698                 );1699             }1700             return Expression.GreaterThanOrEqual(left, right);1701         }1702 1703         Expression GenerateLessThan(Expression left, Expression right) {1704             if (left.Type == typeof(string)) {1705                 return Expression.LessThan(1706                     GenerateStaticMethodCall("Compare", left, right),1707                     Expression.Constant(0)1708                 );1709             }1710             return Expression.LessThan(left, right);1711         }1712 1713         Expression GenerateLessThanEqual(Expression left, Expression right) {1714             if (left.Type == typeof(string)) {1715                 return Expression.LessThanOrEqual(1716                     GenerateStaticMethodCall("Compare", left, right),1717                     Expression.Constant(0)1718                 );1719             }1720             return Expression.LessThanOrEqual(left, right);1721         }1722 1723         Expression GenerateAdd(Expression left, Expression right) {1724             if (left.Type == typeof(string) && right.Type == typeof(string)) {1725                 return GenerateStaticMethodCall("Concat", left, right);1726             }1727             return Expression.Add(left, right);1728         }1729 1730         Expression GenerateSubtract(Expression left, Expression right) {1731             return Expression.Subtract(left, right);1732         }1733 1734         Expression GenerateStringConcat(Expression left, Expression right) {1735             return Expression.Call(1736                 null,1737                 typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }),1738                 new[] { left, right });1739         }1740 1741         MethodInfo GetStaticMethod(string methodName, Expression left, Expression right) {1742             return left.Type.GetMethod(methodName, new[] { left.Type, right.Type });1743         }1744 1745         Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right) {1746             return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right });1747         }1748 1749         void SetTextPos(int pos) {1750             textPos = pos;1751             ch = textPos < textLen ? text[textPos] : '\0';1752         }1753 1754         void NextChar() {1755             if (textPos < textLen) textPos++;1756             ch = textPos < textLen ? text[textPos] : '\0';1757         }1758 1759         void NextToken() {1760             while (Char.IsWhiteSpace(ch)) NextChar();1761             TokenId t;1762             int tokenPos = textPos;1763             switch (ch) {1764                 case '!':1765                     NextChar();1766                     if (ch == '=') {1767                         NextChar();1768                         t = TokenId.ExclamationEqual;1769                     }1770                     else {1771                         t = TokenId.Exclamation;1772                     }1773                     break;1774                 case '%':1775                     NextChar();1776                     t = TokenId.Percent;1777                     break;1778                 case '&':1779                     NextChar();1780                     if (ch == '&') {1781                         NextChar();1782                         t = TokenId.DoubleAmphersand;1783                     }1784                     else {1785                         t = TokenId.Amphersand;1786                     }1787                     break;1788                 case '(':1789                     NextChar();1790                     t = TokenId.OpenParen;1791                     break;1792                 case ')':1793                     NextChar();1794                     t = TokenId.CloseParen;1795                     break;1796                 case '*':1797                     NextChar();1798                     t = TokenId.Asterisk;1799                     break;1800                 case '+':1801                     NextChar();1802                     t = TokenId.Plus;1803                     break;1804                 case ',':1805                     NextChar();1806                     t = TokenId.Comma;1807                     break;1808                 case '-':1809                     NextChar();1810                     t = TokenId.Minus;1811                     break;1812                 case '.':1813                     NextChar();1814                     t = TokenId.Dot;1815                     break;1816                 case '/':1817                     NextChar();1818                     t = TokenId.Slash;1819                     break;1820                 case ':':1821                     NextChar();1822                     t = TokenId.Colon;1823                     break;1824                 case '<':1825                     NextChar();1826                     if (ch == '=') {1827                         NextChar();1828                         t = TokenId.LessThanEqual;1829                     }1830                     else if (ch == '>') {1831                         NextChar();1832                         t = TokenId.LessGreater;1833                     }1834                     else {1835                         t = TokenId.LessThan;1836                     }1837                     break;1838                 case '=':1839                     NextChar();1840                     if (ch == '=') {1841                         NextChar();1842                         t = TokenId.DoubleEqual;1843                     }1844                     else {1845                         t = TokenId.Equal;1846                     }1847                     break;1848                 case '>':1849                     NextChar();1850                     if (ch == '=') {1851                         NextChar();1852                         t = TokenId.GreaterThanEqual;1853                     }1854                     else {1855                         t = TokenId.GreaterThan;1856                     }1857                     break;1858                 case '?':1859                     NextChar();1860                     t = TokenId.Question;1861                     break;1862                 case '[':1863                     NextChar();1864                     t = TokenId.OpenBracket;1865                     break;1866                 case ']':1867                     NextChar();1868                     t = TokenId.CloseBracket;1869                     break;1870                 case '|':1871                     NextChar();1872                     if (ch == '|') {1873                         NextChar();1874                         t = TokenId.DoubleBar;1875                     }1876                     else {1877                         t = TokenId.Bar;1878                     }1879                     break;1880                 case '"':1881                 case '\'':1882                     char quote = ch;1883                     do {1884                         NextChar();1885                         while (textPos < textLen && ch != quote) NextChar();1886                         if (textPos == textLen)1887                             throw ParseError(textPos, Res.UnterminatedStringLiteral);1888                         NextChar();1889                     } while (ch == quote);1890                     t = TokenId.StringLiteral;1891                     break;1892                 default:1893                     if (Char.IsLetter(ch) || ch == '@' || ch == '_') {1894                         do {1895                             NextChar();1896                         } while (Char.IsLetterOrDigit(ch) || ch == '_');1897                         t = TokenId.Identifier;1898                         break;1899                     }1900                     if (Char.IsDigit(ch)) {1901                         t = TokenId.IntegerLiteral;1902                         do {1903                             NextChar();1904                         } while (Char.IsDigit(ch));1905                         if (ch == '.') {1906                             t = TokenId.RealLiteral;1907                             NextChar();1908                             ValidateDigit();1909                             do {1910                                 NextChar();1911                             } while (Char.IsDigit(ch));1912                         }1913                         if (ch == 'E' || ch == 'e') {1914                             t = TokenId.RealLiteral;1915                             NextChar();1916                             if (ch == '+' || ch == '-') NextChar();1917                             ValidateDigit();1918                             do {1919                                 NextChar();1920                             } while (Char.IsDigit(ch));1921                         }1922                         if (ch == 'F' || ch == 'f') NextChar();1923                         break;1924                     }1925                     if (textPos == textLen) {1926                         t = TokenId.End;1927                         break;1928                     }1929                     throw ParseError(textPos, Res.InvalidCharacter, ch);1930             }1931             token.id = t;1932             token.text = text.Substring(tokenPos, textPos - tokenPos);1933             token.pos = tokenPos;1934         }1935 1936         bool TokenIdentifierIs(string id) {1937             return token.id == TokenId.Identifier && String.Equals(id, token.text, StringComparison.OrdinalIgnoreCase);1938         }1939 1940         string GetIdentifier() {1941             ValidateToken(TokenId.Identifier, Res.IdentifierExpected);1942             string id = token.text;1943             if (id.Length > 1 && id[0] == '@') id = id.Substring(1);1944             return id;1945         }1946 1947         void ValidateDigit() {1948             if (!Char.IsDigit(ch)) throw ParseError(textPos, Res.DigitExpected);1949         }1950 1951         void ValidateToken(TokenId t, string errorMessage) {1952             if (token.id != t) throw ParseError(errorMessage);1953         }1954 1955         void ValidateToken(TokenId t) {1956             if (token.id != t) throw ParseError(Res.SyntaxError);1957         }1958 1959         Exception ParseError(string format, params object[] args) {1960             return ParseError(token.pos, format, args);1961         }1962 1963         Exception ParseError(int pos, string format, params object[] args) {1964             return new ParseException(string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args), pos);1965         }1966 1967         static Dictionary<string, object> CreateKeywords() {1968             Dictionary<string, object> d = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);1969             d.Add("true", trueLiteral);1970             d.Add("false", falseLiteral);1971             d.Add("null", nullLiteral);1972             d.Add(keywordIt, keywordIt);1973             d.Add(keywordIif, keywordIif);1974             d.Add(keywordNew, keywordNew);1975             foreach (Type type in predefinedTypes) d.Add(type.Name, type);1976             return d;1977         }1978     }1979 1980     static class Res1981     {1982         public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once";1983         public const string ExpressionTypeMismatch = "Expression of type '{0}' expected";1984         public const string ExpressionExpected = "Expression expected";1985         public const string InvalidCharacterLiteral = "Character literal must contain exactly one character";1986         public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'";1987         public const string InvalidRealLiteral = "Invalid real literal '{0}'";1988         public const string UnknownIdentifier = "Unknown identifier '{0}'";1989         public const string NoItInScope = "No 'it' is in scope";1990         public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments";1991         public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'";1992         public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other";1993         public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other";1994         public const string MissingAsClause = "Expression is missing an 'as' clause";1995         public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression";1996         public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form";1997         public const string NoMatchingConstructor = "No matching constructor in type '{0}'";1998         public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor";1999         public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'";2000         public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'";2001         public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible";2002         public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value";2003         public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'";2004         public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'";2005         public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists";2006         public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported";2007         public const string InvalidIndex = "Array index must be an integer expression";2008         public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'";2009         public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'";2010         public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'";2011         public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'";2012         public const string UnterminatedStringLiteral = "Unterminated string literal";2013         public const string InvalidCharacter = "Syntax error '{0}'";2014         public const string DigitExpected = "Digit expected";2015         public const string SyntaxError = "Syntax error";2016         public const string TokenExpected = "{0} expected";2017         public const string ParseExceptionFormat = "{0} (at index {1})";2018         public const string ColonExpected = "':' expected";2019         public const string OpenParenExpected = "'(' expected";2020         public const string CloseParenOrOperatorExpected = "')' or operator expected";2021         public const string CloseParenOrCommaExpected = "')' or ',' expected";2022         public const string DotOrOpenParenExpected = "'.' or '(' expected";2023         public const string OpenBracketExpected = "'[' expected";2024         public const string CloseBracketOrCommaExpected = "']' or ',' expected";2025         public const string IdentifierExpected = "Identifier expected";2026     }2027 }

4.~/Controllers/下更新控制器StoreManagerController

View Code
 1         public ActionResult Index(string sortOrder) 2         { 3             //return View(); 4             //var albums = db.Albums.Include("Genre").Include("Artist");  5             //return View(albums.ToList()); 6  7             #region ViewBag资源 8             ViewBag.CreateLink = Resource.CreateLink; 9             ViewBag.EditLink = Resource.EditLink;10             ViewBag.DetailsLink = Resource.DetailsLink;11             ViewBag.DeleteLink = Resource.DeleteLink;12             ViewBag.GenreDisplay = Resource.GenreDisplay;13             ViewBag.ArtistDisplay = Resource.ArtistDisplay;14             ViewBag.TitleDisplay = Resource.TitleDisplay;15             ViewBag.PriceDisplay = Resource.PriceDisplay;16             #endregion17 18             #region ViewBag排序PARAMS19             ViewBag.GenreSortParam = (sortOrder == "Genre.Name") ? "Genre.Name desc" : "Genre.Name";20             ViewBag.ArtistSortParam = (sortOrder == "Artist.Name") ? "Artist.Name desc" : "Artist.Name";21             ViewBag.TitleSortParam = (sortOrder == "Title") ? "Title desc" : "Title";22             ViewBag.PriceSortParam = (sortOrder == "Price") ? "Price desc" : "Price";23             #endregion24 25             //默认的排序顺序26             if (String.IsNullOrEmpty(sortOrder))27             {28                 sortOrder = "Title desc";29             }30 31             var albums = db.Albums.OrderBy(sortOrder);32             return View(albums.ToList());33         }


TAG: