/// <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 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; } 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; }
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) { // see if we implement this interface exactly once Type[] interfaces = inputType.GetInterfaces(); Type targetType = null; Type genTypeDef = ParameterType.GetGenericTypeDefinition(); foreach (Type ifaceType in interfaces) { if (ifaceType.IsGenericType && ifaceType.GetGenericTypeDefinition() == genTypeDef) { if (targetType == null) { // we may have a match, figure out the type... targetType = InferGenericType(genericParameter, ifaceType, ParameterType, prevConstraints); } else { // multiple interface implementations match return null; } } } prevConstraints[genericParameter] = targetType; return targetType; } 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) { if (curType.GetGenericTypeDefinition() == genType) { // TODO: Merge w/ the interface logic above Type unboundType = ParameterType; Type res = InferGenericType(genericParameter, curType, unboundType, prevConstraints); prevConstraints[genericParameter] = res; return res; } } curType = curType.BaseType; } return null; }