/// <summary> /// Parsers an invocation operation. /// </summary> protected virtual string OnParseInvoke(DynamicNode.Invoke obj, IParameterCollection pc, bool nulls) { if (obj.Arguments == null || obj.Arguments.Length == 0) { return(string.Empty); } StringBuilder sb = new StringBuilder(); foreach (var arg in obj.Arguments) { if (arg is string) { sb.Append((string)arg); } else { sb.Append(Parse(arg, pc, nulls)); } } string host = obj.Host == null ? null : Parse(obj.Host, pc, nulls); string name = host == null?sb.ToString() : "{0}{1}".FormatWith(host, sb.ToString()); return(name); }
/// <summary> /// Parses a method invocation. /// This method is used to implement the virtual extensions feature, including: /// <para>Argument level:</para> /// <para>- x.Not(...) => (NOT ...)</para> /// <para>- x.Distinct(expression) => DISTINCT expression</para> /// <para>Element level:</para> /// <para>- x.Element.As(name) => Element AS name</para> /// <para>- x.Element.In(arg, ...) => Element IN (arg, ...)</para> /// <para>- x.Element.NotIn(arg, ...) => NOT Element IN (arg, ...)</para> /// <para>- x.Element.InList(...) / .NotInList(...) => Interprets the single argument as a list</para> /// <para>- x.Element.Between(arg1, arg2) => Element BETWEEN arg1 AND arg2</para> /// <para>- x.Element.Like(arg) => Element LIKE arg</para> /// <para>- x.Element.NotLike(arg) => Element NOT LIKE arg</para> /// <para>Default case:</para> /// <para>- The default case where the name of the method and its arguments are parsed as-is.</para> /// </summary> protected virtual string OnParseMethod(DynamicNode.Method obj, IParameterCollection pc, bool nulls) { string name = obj.Name.ToUpper(); string parent = obj.Host == null ? null : Parse(obj.Host, pc, nulls); string item = null; StringBuilder sb = new StringBuilder(); string str = null; int i = 0; IEnumerable iter = null; // Root-level methods... if (parent == null) { switch (name) { case "NOT": if (obj.Arguments == null) { throw new ArgumentException("NOT() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("NOT() requires just one argument."); } item = Parse(obj.Arguments[0], pc, nulls); return("(NOT {0})".FormatWith(item)); case "DISTINCT": if (obj.Arguments == null) { throw new ArgumentException("DISTINCT() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("DISTINCT() requires just one argument."); } item = Parse(obj.Arguments[0], pc, nulls); return("DISTINCT {0}".FormatWith(item)); } } // Item-level methods... switch (name) { case "AS": if (obj.Arguments == null) { throw new ArgumentException("AS() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("AS() requires just one argument."); } item = Parse(obj.Arguments[0], pc, nulls); return("{0} AS {1}".FormatWith(parent, item)); case "IN": if (obj.Arguments == null) { throw new ArgumentException("IN() argument list is null."); } if (obj.Arguments.Length == 0) { throw new ArgumentException("IN() requires at least one argument."); } for (i = 0; i < obj.Arguments.Length; i++) { str = Parse(obj.Arguments[i], pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return("{0} IN ({1})".FormatWith(parent, item)); case "NOTIN": if (obj.Arguments == null) { throw new ArgumentException("NOTIN() argument list is null."); } if (obj.Arguments.Length == 0) { throw new ArgumentException("NOTIN() requires at least one argument."); } for (i = 0; i < obj.Arguments.Length; i++) { str = Parse(obj.Arguments[i], pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return("NOT {0} IN ({1})".FormatWith(parent, item)); case "INLIST": if (obj.Arguments == null) { throw new ArgumentException("INLIST() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("INLIST() requires just one argument."); } iter = obj.Arguments[0] as IEnumerable; if (iter == null) { throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch())); } foreach (var temp in iter) { str = Parse(temp, pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return("{0} IN ({1})".FormatWith(parent, item)); case "NOTINLIST": if (obj.Arguments == null) { throw new ArgumentException("NOTINLIST() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("NOTINLIST() requires just one argument."); } iter = obj.Arguments[0] as IEnumerable; if (iter == null) { throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch())); } foreach (var temp in iter) { str = Parse(temp, pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return("NOT {0} IN ({1})".FormatWith(parent, item)); case "BETWEEN": if (obj.Arguments == null) { throw new ArgumentException("BETWEEN() argument list is null."); } if (obj.Arguments.Length != 2) { throw new ArgumentException("BETWEEN() requires two arguments."); } item = Parse(obj.Arguments[0], pc, nulls); str = Parse(obj.Arguments[1], pc, nulls); return("{0} BETWEEN ({1}) AND ({2})".FormatWith(parent, item, str)); case "LIKE": if (obj.Arguments == null) { throw new ArgumentException("LIKE() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("LIKE() requires just one argument."); } item = Parse(obj.Arguments[0], pc, nulls); return("{0} LIKE ({1})".FormatWith(parent, item)); case "NOTLIKE": if (obj.Arguments == null) { throw new ArgumentException("NOTLIKE() argument list is null."); } if (obj.Arguments.Length != 1) { throw new ArgumentException("NOTLIKE() requires just one argument."); } item = Parse(obj.Arguments[0], pc, nulls); return("{0} NOT LIKE ({1})".FormatWith(parent, item)); } // Intercepting "rounded" escape syntax because the "tag" is interpreted as a method name... DynamicNode node = obj; while (node.Host != null) { node = node.Host; } if (((DynamicNode.Argument)node).Name == obj.Name) { node = new DynamicNode.Invoke((DynamicNode.Argument)node, obj.Arguments); item = OnParseInvoke((DynamicNode.Invoke)node, pc, nulls); node.Dispose(); string host = obj.Host == null ? null : Parse(obj.Host, pc, nulls); string temp = host == null ? item : "{0}{1}".FormatWith(host, item); return(temp); } // Default case... name = parent == null ? obj.Name : "{0}.{1}".FormatWith(parent, obj.Name); sb.AppendFormat("{0}(", name); if (obj.Arguments != null) { for (i = 0; i < obj.Arguments.Length; i++) { if (i != 0) { sb.Append(", "); } sb.Append(Parse(obj.Arguments[i], pc, nulls)); } } sb.Append(")"); return(sb.ToString()); }
/// <summary> /// Parses a method invocation. /// This method is used to implement the virtual extensions feature, including: /// <para>Argument level:</para> /// <para>- x.Not(...) => (NOT ...)</para> /// <para>- x.Distinct(expression) => DISTINCT expression</para> /// <para>Element level:</para> /// <para>- x.Element.As(name) => Element AS name</para> /// <para>- x.Element.In(arg, ...) => Element IN (arg, ...)</para> /// <para>- x.Element.NotIn(arg, ...) => NOT Element IN (arg, ...)</para> /// <para>- x.Element.InList(...) / .NotInList(...) => Interprets the single argument as a list</para> /// <para>- x.Element.Between(arg1, arg2) => Element BETWEEN arg1 AND arg2</para> /// <para>- x.Element.Like(arg) => Element LIKE arg</para> /// <para>- x.Element.NotLike(arg) => Element NOT LIKE arg</para> /// <para>Default case:</para> /// <para>- The default case where the name of the method and its arguments are parsed as-is.</para> /// </summary> protected virtual string OnParseMethod(DynamicNode.Method obj, IParameterCollection pc, bool nulls) { string name = obj.Name.ToUpper(); string parent = obj.Host == null ? null : Parse(obj.Host, pc, nulls); string item = null; StringBuilder sb = new StringBuilder(); string str = null; int i = 0; IEnumerable iter = null; // Root-level methods... if (parent == null) { switch (name) { case "NOT": if (obj.Arguments == null) throw new ArgumentException("NOT() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("NOT() requires just one argument."); item = Parse(obj.Arguments[0], pc, nulls); return "(NOT {0})".FormatWith(item); case "DISTINCT": if (obj.Arguments == null) throw new ArgumentException("DISTINCT() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("DISTINCT() requires just one argument."); item = Parse(obj.Arguments[0], pc, nulls); return "DISTINCT {0}".FormatWith(item); } } // Item-level methods... switch (name) { case "AS": if (obj.Arguments == null) throw new ArgumentException("AS() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("AS() requires just one argument."); item = Parse(obj.Arguments[0], pc, nulls); return "{0} AS {1}".FormatWith(parent, item); case "IN": if (obj.Arguments == null) throw new ArgumentException("IN() argument list is null."); if (obj.Arguments.Length == 0) throw new ArgumentException("IN() requires at least one argument."); for (i = 0; i < obj.Arguments.Length; i++) { str = Parse(obj.Arguments[i], pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return "{0} IN ({1})".FormatWith(parent, item); case "NOTIN": if (obj.Arguments == null) throw new ArgumentException("NOTIN() argument list is null."); if (obj.Arguments.Length == 0) throw new ArgumentException("NOTIN() requires at least one argument."); for (i = 0; i < obj.Arguments.Length; i++) { str = Parse(obj.Arguments[i], pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return "NOT {0} IN ({1})".FormatWith(parent, item); case "INLIST": if (obj.Arguments == null) throw new ArgumentException("INLIST() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("INLIST() requires just one argument."); iter = obj.Arguments[0] as IEnumerable; if (iter == null) throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch())); foreach (var temp in iter) { str = Parse(temp, pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return "{0} IN ({1})".FormatWith(parent, item); case "NOTINLIST": if (obj.Arguments == null) throw new ArgumentException("NOTINLIST() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("NOTINLIST() requires just one argument."); iter = obj.Arguments[0] as IEnumerable; if (iter == null) throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch())); foreach (var temp in iter) { str = Parse(temp, pc, nulls); item = item == null ? str : "{0}, {1}".FormatWith(item, str); } return "NOT {0} IN ({1})".FormatWith(parent, item); case "BETWEEN": if (obj.Arguments == null) throw new ArgumentException("BETWEEN() argument list is null."); if (obj.Arguments.Length != 2) throw new ArgumentException("BETWEEN() requires two arguments."); item = Parse(obj.Arguments[0], pc, nulls); str = Parse(obj.Arguments[1], pc, nulls); return "{0} BETWEEN ({1}) AND ({2})".FormatWith(parent, item, str); case "LIKE": if (obj.Arguments == null) throw new ArgumentException("LIKE() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("LIKE() requires just one argument."); item = Parse(obj.Arguments[0], pc, nulls); return "{0} LIKE ({1})".FormatWith(parent, item); case "NOTLIKE": if (obj.Arguments == null) throw new ArgumentException("NOTLIKE() argument list is null."); if (obj.Arguments.Length != 1) throw new ArgumentException("NOTLIKE() requires just one argument."); item = Parse(obj.Arguments[0], pc, nulls); return "{0} NOT LIKE ({1})".FormatWith(parent, item); } // Intercepting "rounded" escape syntax because the "tag" is interpreted as a method name... DynamicNode node = obj; while (node.Host != null) node = node.Host; if (((DynamicNode.Argument)node).Name == obj.Name) { node = new DynamicNode.Invoke((DynamicNode.Argument)node, obj.Arguments); item = OnParseInvoke((DynamicNode.Invoke)node, pc, nulls); node.Dispose(); string host = obj.Host == null ? null : Parse(obj.Host, pc, nulls); string temp = host == null ? item : "{0}{1}".FormatWith(host, item); return temp; } // Default case... name = parent == null ? obj.Name : "{0}.{1}".FormatWith(parent, obj.Name); sb.AppendFormat("{0}(", name); if (obj.Arguments != null) { for (i = 0; i < obj.Arguments.Length; i++) { if (i != 0) sb.Append(", "); sb.Append(Parse(obj.Arguments[i], pc, nulls)); } } sb.Append(")"); return sb.ToString(); }