static private IsEligibleExtensionMethod ( ICompilation compilation, CSharpConversions conversions, IType targetType, IMethod method, bool useTypeInference, IType &outInferredTypes ) : bool | ||
compilation | ICompilation | |
conversions | CSharpConversions | |
targetType | IType | |
method | IMethod | |
useTypeInference | bool | |
outInferredTypes | IType | |
Результат | bool |
static bool IsEligibleExtensionMethod(ICompilation compilation, CSharpConversions conversions, IType targetType, IMethod method, bool useTypeInference, out IType[] outInferredTypes)
{
outInferredTypes = null;
if (targetType == null)
return true;
if (method.Parameters.Count == 0)
return false;
IType thisParameterType = method.Parameters[0].Type;
if (useTypeInference && method.TypeParameters.Count > 0) {
// We need to infer type arguments from targetType:
TypeInference ti = new TypeInference(compilation, conversions);
ResolveResult[] arguments = { new ResolveResult(targetType) };
IType[] parameterTypes = { method.Parameters[0].Type };
bool success;
var inferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, parameterTypes, out success);
var substitution = new TypeParameterSubstitution(null, inferredTypes);
// Validate that the types that could be inferred (aren't unknown) satisfy the constraints:
bool hasInferredTypes = false;
for (int i = 0; i < inferredTypes.Length; i++) {
if (inferredTypes[i].Kind != TypeKind.Unknown && inferredTypes[i].Kind != TypeKind.UnboundTypeArgument) {
hasInferredTypes = true;
if (!OverloadResolution.ValidateConstraints(method.TypeParameters[i], inferredTypes[i], substitution, conversions))
return false;
} else {
inferredTypes[i] = method.TypeParameters[i]; // do not substitute types that could not be inferred
}
}
if (hasInferredTypes)
outInferredTypes = inferredTypes;
thisParameterType = thisParameterType.AcceptVisitor(substitution);
}
Conversion c = conversions.ImplicitConversion(targetType, thisParameterType);
return c.IsValid && (c.IsIdentityConversion || c.IsReferenceConversion || c.IsBoxingConversion);
}
CSharpResolver::IsEligibleExtensionMethod ( IType targetType, IMethod method, bool useTypeInference, IType &outInferredTypes ) : bool |
/// <summary> /// Gets the eligible extension methods. /// </summary> /// <param name="substituteInferredTypes"> /// Specifies whether to produce a <see cref="SpecializedMethod"/> /// when type arguments could be inferred from <see cref="TargetType"/>. /// This setting is only used for inferred types and has no effect if the type parameters are /// specified explicitly. /// </param> /// <remarks> /// The results are stored in nested lists because they are grouped by using scope. /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }", /// the return value will be /// new List { /// new List { all extensions from MoreExtensions }, /// new List { all extensions from SomeExtensions } /// } /// </remarks> public IEnumerable <IEnumerable <IMethod> > GetEligibleExtensionMethods(bool substituteInferredTypes) { var result = new List <List <IMethod> >(); foreach (var methodGroup in GetExtensionMethods()) { var outputGroup = new List <IMethod>(); foreach (var method in methodGroup) { IType[] inferredTypes; if (CSharpResolver.IsEligibleExtensionMethod(this.TargetType, method, true, out inferredTypes)) { if (substituteInferredTypes && inferredTypes != null) { outputGroup.Add(method.Specialize(new TypeParameterSubstitution(null, inferredTypes))); } else { outputGroup.Add(method); } } } if (outputGroup.Count > 0) { result.Add(outputGroup); } } return(result); }