private ValueDrawerTypeInfo(Type type)
            : base(type)
        {
            Ensure.Argument.NotNull(type, "type");
            Ensure.Argument.Is(type, "type", ValueDrawerTypes.Root);

            if (Type.IsGenericType)
            {
                GenericDefinitionInfo = Type.IsGenericTypeDefinition ? this : Get(Type.GetGenericTypeDefinition());
            }

            var argsForConstraints = GenericDefinitionInfo != null
                ? GenericDefinitionInfo.GenericArguments : GenericArguments;

            if (argsForConstraints.Owner.IsGenericParameter)
            {
                ConstraintsOnOwner = new GenericParameterConstraints(argsForConstraints.Owner);
            }
            if (argsForConstraints.Value.IsGenericParameter)
            {
                ConstraintsOnValue = new GenericParameterConstraints(argsForConstraints.Value);
            }

            if (ConstraintsOnValue != null)
            {
                IsInterfaceDrawer = ConstraintsOnValue.TypeCount > 0 &&
                                    ConstraintsOnValue.Types.All(t => t.IsInterface);
            }
        }
Example #2
0
        private Type BuildImpl(Type ownerType, Type valueType)
        {
            CheckUserArgIfRootIsSpecificType(ownerType, "ownerType", GenericArgOwnerIndex);
            CheckUserArgIfRootIsSpecificType(valueType, "valueType", GenericArgValueIndex);

            Type[] specificArgs;
            if (!TryExtractSpecificGenericArgs(ownerType, valueType, out specificArgs))
            {
                var msg = string.Format(
                    "Unable to extract generic arguments from '{0}' and '{1}' for {2}",
                    ownerType, valueType, DrawerTypeDef);
                throw new TypeLoadException(msg);
            }

            for (int i = 0; i < genericArgs.Count; ++i)
            {
                Type sa = specificArgs[i], ga = genericArgs[i];
                if (!GenericParameterConstraints.Match(sa, ga))
                {
                    throw new ArgumentException(string.Format("Generic argument '{0}' not match with '{1}'.", sa, ga));
                }
            }

            return(DrawerTypeDef.MakeGenericType(specificArgs));
        }
Example #3
0
        private int CompareImpl(Type l, Type r)
        {
            int value;

            if (!CompareUtil.PreCompare(l, r, out value))
            {
                return(value);
            }

            // Use default compare if any argument is not type of ValueDrawer.
            var root = ValueDrawerTypes.Root;

            if (!root.IsAssignableFrom(l) || !root.IsAssignableFrom(r))
            {
                return(Comparer <Type> .Default.Compare(l, r));
            }

            var priorities = ValueDrawerPrioritiesForType.Get(ValueType ?? typeof(object));

            if (priorities != null)
            {
                var lg = l.IsGenericType ? l.GetGenericTypeDefinition() : l;
                var rg = r.IsGenericType ? r.GetGenericTypeDefinition() : r;
                int lp = priorities.GetPriority(lg), rp = priorities.GetPriority(rg);
                return(lp.CompareTo(rp));
            }

            ValueDrawerTypeInfo lInfo = ValueDrawerTypeInfo.Get(l), rInfo = ValueDrawerTypeInfo.Get(r);

            if (lInfo != null && rInfo != null)
            {
                // Interface drawer is more appropriate for interface type.
                if (lInfo.IsInterfaceDrawer && !rInfo.IsInterfaceDrawer)
                {
                    return(ValueType.IsInterface ? 1 : -1);
                }
                if (!lInfo.IsInterfaceDrawer && rInfo.IsInterfaceDrawer)
                {
                    return(ValueType.IsInterface ? -1 : 1);
                }

                GenericParameterConstraints lcov = lInfo.ConstraintsOnValue, rcov = rInfo.ConstraintsOnValue;
                if (lcov != null && rcov != null)
                {
                    if (lcov.TypeCount == 1 && rcov.TypeCount == 1)
                    {
                        Type lIf = rcov.GetType(0), rIf = rcov.GetType(0);
                        if (lIf != rIf)
                        {
                            if (lIf.IsAssignableFrom(rIf))
                            {
                                return(-1);
                            }
                            if (rIf.IsAssignableFrom(lIf))
                            {
                                return(1);
                            }
                        }
                    }
                }

                // The more the drawer type derived, the higher priority it owned.
                return(lInfo.DeriveDepth.CompareTo(rInfo.DeriveDepth));
            }

            return(0);
        }