diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs')
-rw-r--r-- | Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs b/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs new file mode 100644 index 00000000..778cc135 --- /dev/null +++ b/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +#if WINDOWS_UWP + +namespace Xamarin.Forms.Platform.UWP +#else + +namespace Xamarin.Forms.Platform.WinRT +#endif +{ + internal sealed class WindowsExpressionSearch : IExpressionSearch + { + List<object> _results; + Type _targeType; + + public List<T> FindObjects<T>(Expression expression) where T : class + { + _results = new List<object>(); + _targeType = typeof(T); + + Visit(expression); + + List<T> final = _results.Cast<T>().ToList(); + _results = null; + return final; + } + + void Visit(Expression expression) + { + if (expression == null) + return; + + switch (expression.NodeType) + { + case ExpressionType.Negate: + case ExpressionType.NegateChecked: + case ExpressionType.Not: + case ExpressionType.Convert: + case ExpressionType.ConvertChecked: + case ExpressionType.ArrayLength: + case ExpressionType.Quote: + case ExpressionType.TypeAs: + case ExpressionType.UnaryPlus: + Visit(((UnaryExpression)expression).Operand); + break; + case ExpressionType.Add: + case ExpressionType.AddChecked: + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + case ExpressionType.Divide: + case ExpressionType.Modulo: + case ExpressionType.Power: + case ExpressionType.And: + case ExpressionType.AndAlso: + case ExpressionType.Or: + case ExpressionType.OrElse: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.Coalesce: + case ExpressionType.ArrayIndex: + case ExpressionType.RightShift: + case ExpressionType.LeftShift: + case ExpressionType.ExclusiveOr: + var binary = (BinaryExpression)expression; + Visit(binary.Left); + Visit(binary.Right); + Visit(binary.Conversion); + break; + case ExpressionType.TypeIs: + Visit(((TypeBinaryExpression)expression).Expression); + break; + case ExpressionType.Conditional: + var conditional = (ConditionalExpression)expression; + Visit(conditional.Test); + Visit(conditional.IfTrue); + Visit(conditional.IfFalse); + break; + case ExpressionType.MemberAccess: + VisitMemberAccess((MemberExpression)expression); + break; + case ExpressionType.Call: + var methodCall = (MethodCallExpression)expression; + Visit(methodCall.Object); + VisitList(methodCall.Arguments, Visit); + break; + case ExpressionType.Lambda: + Visit(((LambdaExpression)expression).Body); + break; + case ExpressionType.New: + VisitList(((NewExpression)expression).Arguments, Visit); + break; + case ExpressionType.NewArrayInit: + case ExpressionType.NewArrayBounds: + VisitList(((NewArrayExpression)expression).Expressions, Visit); + break; + case ExpressionType.Invoke: + var invocation = (InvocationExpression)expression; + VisitList(invocation.Arguments, Visit); + Visit(invocation.Expression); + break; + case ExpressionType.MemberInit: + var init = (MemberInitExpression)expression; + VisitList(init.NewExpression.Arguments, Visit); + VisitList(init.Bindings, VisitBinding); + break; + case ExpressionType.ListInit: + var init1 = (ListInitExpression)expression; + VisitList(init1.NewExpression.Arguments, Visit); + VisitList(init1.Initializers, initializer => VisitList(initializer.Arguments, Visit)); + break; + case ExpressionType.Constant: + break; + default: + throw new ArgumentException(string.Format("Unhandled expression type: '{0}'", expression.NodeType)); + } + } + + void VisitBinding(MemberBinding binding) + { + switch (binding.BindingType) + { + case MemberBindingType.Assignment: + Visit(((MemberAssignment)binding).Expression); + break; + case MemberBindingType.MemberBinding: + VisitList(((MemberMemberBinding)binding).Bindings, VisitBinding); + break; + case MemberBindingType.ListBinding: + VisitList(((MemberListBinding)binding).Initializers, initializer => VisitList(initializer.Arguments, Visit)); + break; + default: + throw new ArgumentException(string.Format("Unhandled binding type '{0}'", binding.BindingType)); + } + } + + static void VisitList<TList>(IEnumerable<TList> list, Action<TList> visitor) + { + foreach (TList element in list) + { + visitor(element); + } + } + + // All important magic happens here + void VisitMemberAccess(MemberExpression member) + { + if (member.Expression is ConstantExpression && member.Member is FieldInfo) + { + object container = ((ConstantExpression)member.Expression).Value; + object value = ((FieldInfo)member.Member).GetValue(container); + + if (_targeType.IsInstanceOfType(value)) + { + _results.Add(value); + } + } + Visit(member.Expression); + } + } +}
\ No newline at end of file |