/// <summary> /// Attempts to call a method on the dynamic object /// </summary> /// <param name="binder"></param> /// <param name="args"></param> /// <param name="result"></param> /// <returns></returns> public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var runtimeCache = ApplicationContext.Current != null ? ApplicationContext.Current.ApplicationCache.RuntimeCache : new NullCacheProvider(); var attempt = DynamicInstanceHelper.TryInvokeMember(runtimeCache, this, binder, args, new[] { typeof(DynamicPublishedContent) }); if (attempt.Success) { result = attempt.Result.ObjectResult; //need to check the return type and possibly cast if result is from an extension method found if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod) { //we don't need to cast if it is already DynamicPublishedContent if (attempt.Result.ObjectResult != null && (!(attempt.Result.ObjectResult is DynamicPublishedContent))) { if (attempt.Result.ObjectResult is IPublishedContent) { result = new DynamicPublishedContent((IPublishedContent)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <DynamicPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <DynamicPublishedContent>)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <IPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <IPublishedContent>)attempt.Result.ObjectResult); } } } return(true); } //this is the result of an extension method execution gone wrong so we return dynamic null if (attempt.Result != null && attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod && attempt.Exception is TargetInvocationException) { result = DynamicNull.Null; return(true); } result = null; return(false); }
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { //TODO: Nowhere here are we checking if args is the correct length! //NOTE: For many of these we could actually leave them out since we are executing custom extension methods and because // we implement IEnumerable<T> they will execute just fine, however, to do that will be quite a bit slower than checking here. var firstArg = args.FirstOrDefault(); //this is to check for 'DocumentTypeAlias' vs 'NodeTypeAlias' for compatibility if (firstArg != null && firstArg.ToString().InvariantStartsWith("NodeTypeAlias")) { firstArg = "DocumentTypeAlias" + firstArg.ToString().Substring("NodeTypeAlias".Length); } var name = binder.Name; if (name == "Single") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] {} : args.Skip(1).ToArray(); var single = Single <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(single); return(true); } if (name == "SingleOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var single = SingleOrDefault <DynamicPublishedContent>(predicate, values); if (single == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(single); } return(true); } if (name == "First") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = First <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(first); return(true); } if (name == "FirstOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var first = FirstOrDefault <DynamicPublishedContent>(predicate, values); if (first == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(first); } return(true); } if (name == "Last") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = Last <DynamicPublishedContent>(predicate, values); result = new DynamicPublishedContent(last); return(true); } if (name == "LastOrDefault") { string predicate = firstArg == null ? "" : firstArg.ToString(); var values = predicate.IsNullOrWhiteSpace() ? new object[] { } : args.Skip(1).ToArray(); var last = LastOrDefault <DynamicPublishedContent>(predicate, values); if (last == null) { result = DynamicNull.Null; } else { result = new DynamicPublishedContent(last); } return(true); } if (name == "Where") { string predicate = firstArg.ToString(); var values = args.Skip(1).ToArray(); //TODO: We are pre-resolving the where into a ToList() here which will have performance impacts if there where clauses // are nested! We should somehow support an QueryableDocumentList! result = new DynamicPublishedContentList(Where <DynamicPublishedContent>(predicate, values).ToList()); return(true); } if (name == "OrderBy") { //TODO: We are pre-resolving the where into a ToList() here which will have performance impacts if there where clauses // are nested! We should somehow support an QueryableDocumentList! result = new DynamicPublishedContentList(OrderBy <DynamicPublishedContent>(firstArg.ToString()).ToList()); return(true); } if (name == "Take") { result = new DynamicPublishedContentList(this.Take <DynamicPublishedContent>((int)firstArg)); return(true); } if (name == "Skip") { result = new DynamicPublishedContentList(this.Skip <DynamicPublishedContent>((int)firstArg)); return(true); } if (name == "InGroupsOf") { int groupSize; if (int.TryParse(firstArg.ToString(), out groupSize)) { result = InGroupsOf(groupSize); return(true); } result = DynamicNull.Null; return(true); } if (name == "GroupedInto") { int groupCount; if (int.TryParse(firstArg.ToString(), out groupCount)) { result = GroupedInto(groupCount); return(true); } result = DynamicNull.Null; return(true); } if (name == "GroupBy") { result = GroupBy(firstArg.ToString()); return(true); } if (name == "Average" || name == "Min" || name == "Max" || name == "Sum") { result = Aggregate(args, name); return(true); } if (name == "Union") { // check DynamicPublishedContentList before IEnumerable<...> because DynamicPublishedContentList // is IEnumerable<...> so ... the check on DynamicPublishedContentList would never be reached. var firstArgAsDynamicPublishedContentList = firstArg as DynamicPublishedContentList; if (firstArgAsDynamicPublishedContentList != null) { result = new DynamicPublishedContentList(Items.Union((firstArgAsDynamicPublishedContentList).Items)); return(true); } var firstArgAsIEnumerable = firstArg as IEnumerable <DynamicPublishedContent>; if (firstArgAsIEnumerable != null) { result = new DynamicPublishedContentList(Items.Union(firstArgAsIEnumerable)); return(true); } } if (name == "Except") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(Items.Except(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } } if (name == "Intersect") { if ((firstArg as IEnumerable <DynamicPublishedContent>) != null) { result = new DynamicPublishedContentList(Items.Intersect(firstArg as IEnumerable <DynamicPublishedContent>, new DynamicPublishedContentIdEqualityComparer())); return(true); } } if (name == "Distinct") { result = new DynamicPublishedContentList(Items.Distinct(new DynamicPublishedContentIdEqualityComparer())); return(true); } if (name == "Pluck" || name == "Select") { result = Pluck(args); return(true); } //ok, now lets try to match by member, property, extensino method var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[] { typeof(IEnumerable <DynamicPublishedContent>), typeof(DynamicPublishedContentList) }); if (attempt.Success) { result = attempt.Result.ObjectResult; //need to check the return type and possibly cast if result is from an extension method found if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod) { //we don't need to cast if the result is already DynamicPublishedContentList if (attempt.Result.ObjectResult != null && (!(attempt.Result.ObjectResult is DynamicPublishedContentList))) { if (attempt.Result.ObjectResult is IPublishedContent) { result = new DynamicPublishedContent((IPublishedContent)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <DynamicPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <DynamicPublishedContent>)attempt.Result.ObjectResult); } else if (attempt.Result.ObjectResult is IEnumerable <IPublishedContent> ) { result = new DynamicPublishedContentList((IEnumerable <IPublishedContent>)attempt.Result.ObjectResult); } } } return(true); } //this is the result of an extension method execution gone wrong so we return dynamic null if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod && attempt.Exception != null && attempt.Exception is TargetInvocationException) { result = DynamicNull.Null; return(true); } result = null; return(false); }