Provides information about the result of a custom object which dynamically infers back types. Currently only used for invokable objects to feedback the types for a delegate type.
Ejemplo n.º 1
0
        /// <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));
        }
Ejemplo n.º 2
0
            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);
            }