File: System.Activities.Presentation\System\Activities\Presentation\TypeUtilities.cs
Project: ndp\cdf\src\NetFx40\Tools\System.Activities.Presentation.csproj (System.Activities.Presentation)
//----------------------------------------------------------------
// <copyright company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//----------------------------------------------------------------
 
namespace System.Activities.Presentation
{
    using System.Reflection;
    using System.Runtime;
 
    internal static class TypeUtilities
    {
        // returns true if the generic parameter can be subsituted by the candidate.
        // Sometime if the generic parameter is too complex, this method will return a false positive, but it's fine.
        public static bool CanSubstituteGenericParameter(Type genericParameter, Type candidate)
        {
            Fx.Assert(genericParameter != null, "genericParameter should not be null");
            Fx.Assert(genericParameter.IsGenericParameter == true, "genericParameter should be a valid generic parameter");
 
            if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.SpecialConstraintMask))
            {
                if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.ReferenceTypeConstraint))
                {
                    if (!candidate.IsClass && !candidate.IsInterface)
                    {
                        return false;
                    }
                }
 
                if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.DefaultConstructorConstraint))
                {
                    if (!TypeUtilities.CanCreateInstanceUsingDefaultConstructor(candidate))
                    {
                        return false;
                    }
                }
 
                if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint))
                {
                    if (!candidate.IsValueType)
                    {
                        return false;
                    }
 
                    if (candidate.IsGenericType && candidate.GetGenericTypeDefinition() != typeof(Nullable<>))
                    {
                        return false;
                    }
                }
            }
 
            foreach (Type constraint in genericParameter.GetGenericParameterConstraints())
            {
                if (constraint.ContainsGenericParameters)
                {
                    // return true for all types because we don't have a good way to find out if the candidate is good or not.
                    // The caller will try to create closed generic type which will tell if the candidate is really good or not.
                    continue;
                }
 
                if (!constraint.IsAssignableFrom(candidate))
                {
                    return false;
                }
            }
 
            return true;
        }
 
        public static bool CanCreateInstanceUsingDefaultConstructor(Type type)
        {
            Fx.Assert(type != null, "type could not be null");
 
            return type.IsValueType || (!type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null);
        }
 
        public static bool IsTypeCompatible(Type childObjectType, Type parentObjectType)
        {
            if (!parentObjectType.IsGenericTypeDefinition)
            {
                return parentObjectType.IsAssignableFrom(childObjectType);
            }
            else if (parentObjectType.IsInterface)
            {
                Type[] interfaceTypes = childObjectType.GetInterfaces();
                foreach (Type interfaceType in interfaceTypes)
                {
                    if (interfaceType.IsGenericType)
                    {
                        if (interfaceType.GetGenericTypeDefinition() == parentObjectType)
                        {
                            return true;
                        }
                    }
                }
 
                return false;
            }
            else
            {
                Type current = childObjectType;
                while (current != null)
                {
                    if (current.IsGenericType)
                    {
                        if (current.GetGenericTypeDefinition() == parentObjectType)
                        {
                            return true;
                        }
                    }
 
                    current = current.BaseType;
                }
 
                return false;
            }
        }
 
        private static bool ContainsAnyFlag(GenericParameterAttributes attributes, GenericParameterAttributes flags)
        {
            return (attributes & flags) != GenericParameterAttributes.None;
        }
    }
}