/// <summary> /// Provides generic type inference for a single parameter. /// </summary> /// <remarks> /// For example: /// M{T}(T x) /// M{T}(IList{T} x) /// M{T}(ref T x) /// M{T}(T[] x) /// M{T}(ref Dictionary{T,T}[] x) /// </remarks> internal static Type GetInferedType(OverloadResolver /*!*/ resolver, Type /*!*/ genericParameter, Type /*!*/ parameterType, DynamicMetaObject /*!*/ input, Dictionary <Type, Type> /*!*/ binding, Dictionary <DynamicMetaObject, BindingRestrictions> /*!*/ restrictions) { if (parameterType.IsSubclassOf(typeof(Delegate))) { // see if we have an invokable object which can be used to infer into this delegate if (input is IInferableInvokable invokeInfer) { InferenceResult inference = invokeInfer.GetInferredType(parameterType, genericParameter); if (inference != null) { if (inference.Restrictions != BindingRestrictions.Empty) { restrictions[input] = inference.Restrictions; } binding[genericParameter] = inference.Type; if (ConstraintsViolated(inference.Type, genericParameter, binding)) { return(null); } return(inference.Type); } } } return(GetInferedType(genericParameter, parameterType, resolver.GetGenericInferenceType(input), input.LimitType, binding)); }
public override Type GetInferedType(OverloadResolver resolver, Type genericParameter, DynamicMetaObject input, Dictionary <Type, Type> prevConstraints, Dictionary <DynamicMetaObject, BindingRestrictions> restrictions) { Type inputType = resolver.GetGenericInferenceType(input); if (inputType != null) { prevConstraints[genericParameter] = inputType; if (ConstraintsViolated(inputType, genericParameter, prevConstraints)) { return(null); } } return(inputType); }
public override Type GetInferedType(OverloadResolver resolver, Type genericParameter, DynamicMetaObject input, Dictionary <Type, Type> prevConstraints, Dictionary <DynamicMetaObject, BindingRestrictions> restrictions) { Type inputType = resolver.GetGenericInferenceType(input); if (ParameterType.IsInterface) { // // The argument can implement multiple instantiations of the same generic interface definition, e.g. // ArgType : I<C<X>>, I<D<Y>> // ParamType == I<C<T>> // // Unless X == Y we can't infer T. // Type[] interfaces = inputType.GetInterfaces(); Type match = null; Type genTypeDef = ParameterType.GetGenericTypeDefinition(); foreach (Type ifaceType in interfaces) { if (ifaceType.IsGenericType && ifaceType.GetGenericTypeDefinition() == genTypeDef) { if (!MatchGenericParameter(genericParameter, ifaceType, ParameterType, prevConstraints, ref match)) { return(null); } } } prevConstraints[genericParameter] = match; return(match); } else if (ParameterType.IsArray) { return(prevConstraints[genericParameter] = MatchGenericParameter(genericParameter, input.LimitType, ParameterType, prevConstraints)); } else if (ParameterType.IsByRef) { Type argType = input.LimitType; if (CompilerHelpers.IsStrongBox(argType)) { argType = argType.GetGenericArguments()[0]; } return(prevConstraints[genericParameter] = MatchGenericParameter(genericParameter, argType, ParameterType.GetElementType(), prevConstraints)); } else if (ParameterType.IsSubclassOf(typeof(Delegate))) { // see if we have an invokable object which can be used to infer into this delegate IInferableInvokable invokeInfer = input as IInferableInvokable; if (invokeInfer != null) { InferenceResult inference = invokeInfer.GetInferredType(ParameterType, genericParameter); if (inference != null) { if (inference.Restrictions != BindingRestrictions.Empty) { restrictions[input] = inference.Restrictions; } prevConstraints[genericParameter] = inference.Type; if (ConstraintsViolated(inference.Type, genericParameter, prevConstraints)) { return(null); } return(inference.Type); } } } // see if we're anywhere in our base class hierarchy Type curType = input.LimitType; Type genType = ParameterType.GetGenericTypeDefinition(); while (curType != typeof(object)) { if (curType.IsGenericType && curType.GetGenericTypeDefinition() == genType) { // TODO: Merge w/ the interface logic above return(prevConstraints[genericParameter] = MatchGenericParameter(genericParameter, curType, ParameterType, prevConstraints)); } curType = curType.BaseType; } return(null); }