public List <Movie> DiscoverNewMovies(string action) { var allMovies = _movieService.GetAllMovies(); var allExclusions = _exclusionService.GetAllExclusions(); string allIds = string.Join(",", allMovies.Select(m => m.TmdbId)); string ignoredIds = string.Join(",", allExclusions.Select(ex => ex.TmdbId)); List <MovieResult> results = new List <MovieResult>(); try { results = _radarrAPI.DiscoverMovies(action, (request) => { request.AllowAutoRedirect = true; request.Method = HttpMethod.POST; request.Headers.ContentType = "application/x-www-form-urlencoded"; request.SetContent($"tmdbIds={allIds}&ignoredIds={ignoredIds}"); return(request); }); results = results.Where(m => allMovies.None(mo => mo.TmdbId == m.id) && allExclusions.None(ex => ex.TmdbId == m.id)).ToList(); } catch (RadarrAPIException exception) { _logger.Error(exception, "Failed to discover movies for action {0}!", action); } catch (Exception exception) { _logger.Error(exception, "Failed to discover movies for action {0}!", action); } return(results.SelectList(MapMovie)); }
/// <summary> /// Processes given inputs with on first level then optionally calls subset for second level /// </summary> /// <remarks> /// * Call first function in given inputs /// * Call specified inputs (based on first function results) with second function /// * Fix indices for results of second function /// * Merge the results /// </remarks> public static async Task <IReadOnlyList <TResult> > RunMultiLevelWithMergeAsync <TSource, TResult>( IReadOnlyList <TSource> inputs, Func <IReadOnlyList <TSource>, Task <IReadOnlyList <TResult> > > runFirstLevelAsync, Func <IReadOnlyList <TSource>, Task <IReadOnlyList <TResult> > > runSecondLevelAsync, Func <TResult, TResult, TResult> mergeResults, Func <TResult, bool> useFirstLevelResult) { TResult[] results = new TResult[inputs.Count]; // Get results from first method IReadOnlyList <TResult> initialResults = await runFirstLevelAsync(inputs); // Determine which inputs can use the first level results based on useFirstLevelResult() List <Indexed <TResult> > indexedFirstLevelOnlyResults = new List <Indexed <TResult> >(); List <int> nextLevelIndices = null; for (int i = 0; i < initialResults.Count; i++) { var result = initialResults[i]; if (useFirstLevelResult(result)) { results[i] = result; } else { nextLevelIndices = nextLevelIndices ?? new List <int>(); nextLevelIndices.Add(i); } } // Return early if no misses if (nextLevelIndices == null) { return(initialResults); } // Try fallback for items that failed in first attempt IReadOnlyList <TSource> missedInputs = nextLevelIndices.SelectList(index => inputs[index]); IReadOnlyList <TResult> fallbackResults = await runSecondLevelAsync(missedInputs); for (int i = 0; i < nextLevelIndices.Count; i++) { var originalIndex = nextLevelIndices[i]; var result = fallbackResults[i]; results[originalIndex] = mergeResults(initialResults[originalIndex], result); } return(results); }
public bool IsSatisfiedBy(List <Episode> episodes) { var episodeIds = episodes.SelectList(e => e.Id); var episodeFileIds = episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFileId).Distinct(); foreach (var episodeFileId in episodeFileIds) { var episodesInFile = _episodeService.GetEpisodesByFileId(episodeFileId); if (episodesInFile.Select(e => e.Id).Except(episodeIds).Any()) { return(false); } } return(true); }
public bool IsSatisfiedBy(List <Track> tracks) { var trackIds = tracks.SelectList(e => e.Id); var trackFileIds = tracks.Where(c => c.TrackFileId != 0).Select(c => c.TrackFileId).Distinct(); foreach (var trackFileId in trackFileIds) { var tracksInFile = _trackService.GetTracksByFileId(trackFileId); if (tracksInFile.Select(e => e.Id).Except(trackIds).Any()) { return(false); } } return(true); }
public bool IsSatisfiedBy(List<Episode> episodes) { var episodeIds = episodes.SelectList(e => e.Id); var episodeFileIds = episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFileId).Distinct(); foreach (var episodeFileId in episodeFileIds) { var episodesInFile = _episodeService.GetEpisodesByFileId(episodeFileId); if (episodesInFile.Select(e => e.Id).Except(episodeIds).Any()) { return false; } } return true; }
/// <nodoc /> public void StoreResult(OperationContext context, string path, List <string> machines) { foreach (var machine in machines) { _knownMachines.GetOrAdd(machine, _ => { var machineId = new MachineId(Interlocked.Increment(ref _currentId)); _clusterState.AddMachine(machineId, new MachineLocation(machine)); return(machineId); }); } var pathHash = ComputePathHash(path); var entry = ContentLocationEntry.Create(MachineIdSet.Empty.SetExistence(machines.SelectList(machine => _knownMachines[machine]), true), 0, DateTime.UtcNow); _database.Store(context, pathHash, entry); }
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList <ILInstruction> callArguments, IType constrainedTo = null) { // Used for Call, CallVirt and NewObj var expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = callOpCode }; TranslatedExpression target; if (callOpCode == OpCode.NewObj) { target = default(TranslatedExpression); // no target } else { target = expressionBuilder.TranslateTarget(method, callArguments.FirstOrDefault(), callOpCode == OpCode.Call, constrainedTo); if (callOpCode == OpCode.CallVirt && constrainedTo == null && target.Expression is CastExpression cast && target.ResolveResult is ConversionResolveResult conversion && target.Type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion) { // boxing conversion on call target? // let's see if we can make that implicit: target = target.UnwrapChild(cast.Expression); // we'll need to make sure the boxing effect is preserved expectedTargetDetails.NeedsBoxingConversion = true; } } int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1; // Translate arguments to the expected parameter types var arguments = new List <TranslatedExpression>(method.Parameters.Count); Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count); var expectedParameters = method.Parameters.ToList(); bool isExpandedForm = false; for (int i = 0; i < method.Parameters.Count; i++) { var parameter = expectedParameters[i]; var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i]); if (parameter.IsParams && i + 1 == method.Parameters.Count) { // Parameter is marked params // If the argument is an array creation, inline all elements into the call and add missing default values. // Otherwise handle it normally. if (arg.ResolveResult is ArrayCreateResolveResult acrr && acrr.SizeArguments.Count == 1 && acrr.SizeArguments[0].IsCompileTimeConstant && acrr.SizeArguments[0].ConstantValue is int length) { var expandedParameters = expectedParameters.Take(expectedParameters.Count - 1).ToList(); var expandedArguments = new List <TranslatedExpression>(arguments); if (length > 0) { var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray(); var elementType = ((ArrayType)acrr.Type).ElementType; for (int j = 0; j < length; j++) { expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j)); if (j < arrayElements.Length) { expandedArguments.Add(new TranslatedExpression(arrayElements[j])); } else { expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction()); } } } if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, expandedArguments) == OverloadResolutionErrors.None) { isExpandedForm = true; expectedParameters = expandedParameters; arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach())); continue; } } } arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true)); if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr) { dirExpr.FieldDirection = FieldDirection.Out; } } if (method is VarArgInstanceMethod) { int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount; var argListArg = new UndocumentedExpression(); argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList; int paramIndex = regularParameterCount; var builder = expressionBuilder; argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression)); var argListRR = new ResolveResult(SpecialType.ArgList); arguments = arguments.Take(regularParameterCount) .Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList(); method = (IMethod)method.MemberDefinition; expectedParameters = method.Parameters.ToList(); } var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList(); ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm); if (callOpCode == OpCode.NewObj) { if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { var argumentExpressions = arguments.SelectArray(arg => arg.Expression); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters)) { atce.Initializers.AddRange(argumentExpressions); } else { for (int i = 0; i < argumentExpressions.Length; i++) { atce.Initializers.Add( new NamedExpression { Name = expectedParameters[i].Name, Expression = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder) }); } } return(atce .WithRR(rr)); } else { if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, arguments) != OverloadResolutionErrors.None) { for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } return(new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression)) .WithRR(rr)); } } else { int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) { return(HandleAccessorCall(expectedTargetDetails, method, target, arguments.ToList())); } else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate) { return(new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithRR(rr)); } else if (IsDelegateEqualityComparison(method, arguments)) { return(HandleDelegateEqualityComparison(method, arguments) .WithRR(rr)); } else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) { return(HandleImplicitConversion(method, arguments[0])); } else { bool requireTypeArguments = false; bool targetCasted = false; bool argumentsCasted = false; IType[] typeArguments = Empty <IType> .Array; OverloadResolutionErrors errors; while ((errors = IsUnambiguousCall(expectedTargetDetails, method, target, typeArguments, arguments)) != OverloadResolutionErrors.None) { switch (errors) { case OverloadResolutionErrors.TypeInferenceFailed: case OverloadResolutionErrors.WrongNumberOfTypeArguments: if (requireTypeArguments) { goto default; } requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); continue; default: if (!argumentsCasted) { argumentsCasted = true; for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } else if (!targetCasted) { targetCasted = true; target = target.ConvertTo(method.DeclaringType, expressionBuilder); } else if (!requireTypeArguments) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); } else { break; } continue; } break; } Expression targetExpr = target.Expression; string methodName = method.Name; // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. if (method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression) { targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr); methodName = method.ImplementedInterfaceMembers[0].Name; } var mre = new MemberReferenceExpression(targetExpr, methodName); if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) { mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } var argumentExpressions = arguments.Select(arg => arg.Expression); return(new InvocationExpression(mre, argumentExpressions).WithRR(rr)); } } }
public void SetupInput(string input) { _i = _j = _current = 0; _chunks = new List<string>(); _input = input.Replace("\r\n", "\n"); _inputLength = _input.Length; // Split the input into chunks, // Either delimited by /\n\n/ or // delmited by '\n}' (see rationale above), // depending on the level of optimization. if (Optimization == 0) _chunks.Add(_input); else { var chunkParts = new List<StringBuilder> { new StringBuilder() }; var chunkPart = chunkParts.Last(); var skip = new Regex(@"\G[^\""'{}/\\`]+"); var comment = new Regex(@"\G\/\*(?:[^*\n]|\*+[^\/\n]|\*?(\n))*\*+\/"); var level = 0; var lastBlock = 0; var lastQuote = 0; char? inString = null; for (int i = 0; i < _inputLength; i++) { var match = skip.Match(_input, i); if(match.Success) { chunkPart.Append(match.Value); i += match.Length; if (i == _inputLength) break; } if(i < _inputLength - 1 && _input[i] == '/') { var cc = _input[i + 1]; if(cc == '/' || cc=='*') { match = comment.Match(_input, i); if (match.Success) { i += match.Length; chunkPart.Append(match.Value); if (i == _inputLength) break; } } } var c = _input[i]; if (c == '"' || c == '\'' || c == '`') { if (inString == null) { inString = c; lastQuote = i; } else inString = inString == c ? null : inString; } else if (inString != null && c == '\\' && i < _inputLength - 1) { chunkPart.Append(_input, i, 2); i++; continue; } else if (inString == null && c == '{') { level++; lastBlock = i; } else if (inString == null && c == '}') { level--; if (level < 0) throw new ParsingException("Unexpected '}'", i); chunkPart.Append(c); chunkPart = new StringBuilder(); chunkParts.Add(chunkPart); continue; } chunkPart.Append(c); } if(inString != null) throw new ParsingException(string.Format("Missing closing quote ({0})", inString), lastQuote); if(level > 0) throw new ParsingException("Missing closing '}'", lastBlock); _chunks = chunkParts.SelectList(p => p.ToString()); _input = _chunks.JoinStrings(""); _inputLength = _input.Length; } Advance(0); // skip any whitespace characters at the start. }
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList <ILInstruction> callArguments, IType constrainedTo = null) { // Used for Call, CallVirt and NewObj var expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = callOpCode }; TranslatedExpression target; if (callOpCode == OpCode.NewObj) { target = default(TranslatedExpression); // no target } else { target = expressionBuilder.TranslateTarget( callArguments.FirstOrDefault(), nonVirtualInvocation: callOpCode == OpCode.Call, memberStatic: method.IsStatic, memberDeclaringType: constrainedTo ?? method.DeclaringType); if (constrainedTo == null && target.Expression is CastExpression cast && target.ResolveResult is ConversionResolveResult conversion && target.Type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion) { // boxing conversion on call target? // let's see if we can make that implicit: target = target.UnwrapChild(cast.Expression); // we'll need to make sure the boxing effect is preserved expectedTargetDetails.NeedsBoxingConversion = true; } } int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1; // Translate arguments to the expected parameter types var arguments = new List <TranslatedExpression>(method.Parameters.Count); Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count); var expectedParameters = method.Parameters.ToList(); bool isExpandedForm = false; for (int i = 0; i < method.Parameters.Count; i++) { var parameter = expectedParameters[i]; var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i], parameter.Type); if (parameter.IsParams && i + 1 == method.Parameters.Count) { // Parameter is marked params // If the argument is an array creation, inline all elements into the call and add missing default values. // Otherwise handle it normally. if (arg.ResolveResult is ArrayCreateResolveResult acrr && acrr.SizeArguments.Count == 1 && acrr.SizeArguments[0].IsCompileTimeConstant && acrr.SizeArguments[0].ConstantValue is int length) { var expandedParameters = expectedParameters.Take(expectedParameters.Count - 1).ToList(); var expandedArguments = new List <TranslatedExpression>(arguments); if (length > 0) { var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray(); var elementType = ((ArrayType)acrr.Type).ElementType; for (int j = 0; j < length; j++) { expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j)); if (j < arrayElements.Length) { expandedArguments.Add(new TranslatedExpression(arrayElements[j])); } else { expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction()); } } } if (IsUnambiguousCall(expectedTargetDetails, method, target.ResolveResult, Empty <IType> .Array, expandedArguments, out _) == OverloadResolutionErrors.None) { isExpandedForm = true; expectedParameters = expandedParameters; arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach())); continue; } } } arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true)); if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr && arguments[i].ResolveResult is ByReferenceResolveResult brrr) { dirExpr.FieldDirection = FieldDirection.Out; dirExpr.RemoveAnnotations <ByReferenceResolveResult>(); if (brrr.ElementResult == null) { brrr = new ByReferenceResolveResult(brrr.ElementType, isOut: true); } else { brrr = new ByReferenceResolveResult(brrr.ElementResult, isOut: true); } dirExpr.AddAnnotation(brrr); arguments[i] = new TranslatedExpression(dirExpr); } } if (method is VarArgInstanceMethod) { int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount; var argListArg = new UndocumentedExpression(); argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList; int paramIndex = regularParameterCount; var builder = expressionBuilder; argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression)); var argListRR = new ResolveResult(SpecialType.ArgList); arguments = arguments.Take(regularParameterCount) .Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList(); method = (IMethod)method.MemberDefinition; expectedParameters = method.Parameters.ToList(); } var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList(); if (callOpCode == OpCode.NewObj) { ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm); if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { var argumentExpressions = arguments.SelectArray(arg => arg.Expression); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters)) { atce.Initializers.AddRange(argumentExpressions); } else { for (int i = 0; i < argumentExpressions.Length; i++) { atce.Initializers.Add( new NamedExpression { Name = expectedParameters[i].Name, Expression = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder) }); } } return(atce .WithRR(rr)); } else { if (IsUnambiguousCall(expectedTargetDetails, method, null, Empty <IType> .Array, arguments, out _) != OverloadResolutionErrors.None) { for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } return(new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression)) .WithRR(rr)); } } else { int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) { return(HandleAccessorCall(expectedTargetDetails, method, target, arguments.ToList())); } else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate && !IsNullConditional(target)) { return(new InvocationExpression(target, arguments.Select(arg => arg.Expression)) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm))); } else if (IsDelegateEqualityComparison(method, arguments)) { return(HandleDelegateEqualityComparison(method, arguments) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm))); } else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) { return(HandleImplicitConversion(method, arguments[0])); } else { bool requireTypeArguments = false; bool requireTarget; if (expressionBuilder.HidesVariableWithName(method.Name)) { requireTarget = true; } else { if (method.IsStatic) { requireTarget = !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) || method.Name == ".cctor"; } else if (method.Name == ".ctor") { requireTarget = true; // always use target for base/this-ctor-call, the constructor initializer pattern depends on this } else if (target.Expression is BaseReferenceExpression) { requireTarget = (callOpCode != OpCode.CallVirt && method.IsVirtual); } else { requireTarget = !(target.Expression is ThisReferenceExpression); } } bool targetCasted = false; bool argumentsCasted = false; IType[] typeArguments = Empty <IType> .Array; var targetResolveResult = requireTarget ? target.ResolveResult : null; IParameterizedMember foundMethod; OverloadResolutionErrors errors; while ((errors = IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, typeArguments, arguments, out foundMethod)) != OverloadResolutionErrors.None) { switch (errors) { case OverloadResolutionErrors.TypeInferenceFailed: case OverloadResolutionErrors.WrongNumberOfTypeArguments: if (requireTypeArguments) { goto default; } requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); continue; default: // TODO : implement some more intelligent algorithm that decides which of these fixes (cast args, add target, cast target, add type args) // is best in this case. Additionally we should not cast all arguments at once, but step-by-step try to add only a minimal number of casts. if (!argumentsCasted) { argumentsCasted = true; for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } else if (!requireTarget) { requireTarget = true; targetResolveResult = target.ResolveResult; } else if (!targetCasted) { targetCasted = true; target = target.ConvertTo(method.DeclaringType, expressionBuilder); targetResolveResult = target.ResolveResult; } else if (!requireTypeArguments) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); } else { break; } continue; } // We've given up. foundMethod = method; break; } // Note: after this loop, 'method' and 'foundMethod' may differ, // but as far as allowed by IsAppropriateCallTarget(). Expression targetExpr; string methodName = method.Name; AstNodeCollection <AstType> typeArgumentList; if (requireTarget) { targetExpr = new MemberReferenceExpression(target.Expression, methodName); typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments; // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. if (method.IsExplicitInterfaceImplementation && target.Expression is ThisReferenceExpression) { var castExpression = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), target.Expression); methodName = method.ImplementedInterfaceMembers[0].Name; targetExpr = new MemberReferenceExpression(castExpression, methodName); typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments; } } else { targetExpr = new IdentifierExpression(methodName); typeArgumentList = ((IdentifierExpression)targetExpr).TypeArguments; } if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) { typeArgumentList.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } var argumentExpressions = arguments.Select(arg => arg.Expression); return(new InvocationExpression(targetExpr, argumentExpressions) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, foundMethod, argumentResolveResults, isExpandedForm: isExpandedForm))); } } }