[amd64/tramp] hide interpreter specific trampoline behind ifdef
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / TypeUtilities.cs
1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //----------------------------------------------------------------
6
7 namespace System.Activities.Presentation
8 {
9     using System.Reflection;
10     using System.Runtime;
11
12     internal static class TypeUtilities
13     {
14         // returns true if the generic parameter can be subsituted by the candidate.
15         // Sometime if the generic parameter is too complex, this method will return a false positive, but it's fine.
16         public static bool CanSubstituteGenericParameter(Type genericParameter, Type candidate)
17         {
18             Fx.Assert(genericParameter != null, "genericParameter should not be null");
19             Fx.Assert(genericParameter.IsGenericParameter == true, "genericParameter should be a valid generic parameter");
20
21             if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.SpecialConstraintMask))
22             {
23                 if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.ReferenceTypeConstraint))
24                 {
25                     if (!candidate.IsClass && !candidate.IsInterface)
26                     {
27                         return false;
28                     }
29                 }
30
31                 if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.DefaultConstructorConstraint))
32                 {
33                     if (!TypeUtilities.CanCreateInstanceUsingDefaultConstructor(candidate))
34                     {
35                         return false;
36                     }
37                 }
38
39                 if (ContainsAnyFlag(genericParameter.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint))
40                 {
41                     if (!candidate.IsValueType)
42                     {
43                         return false;
44                     }
45
46                     if (candidate.IsGenericType && candidate.GetGenericTypeDefinition() != typeof(Nullable<>))
47                     {
48                         return false;
49                     }
50                 }
51             }
52
53             foreach (Type constraint in genericParameter.GetGenericParameterConstraints())
54             {
55                 if (constraint.ContainsGenericParameters)
56                 {
57                     // return true for all types because we don't have a good way to find out if the candidate is good or not.
58                     // The caller will try to create closed generic type which will tell if the candidate is really good or not.
59                     continue;
60                 }
61
62                 if (!constraint.IsAssignableFrom(candidate))
63                 {
64                     return false;
65                 }
66             }
67
68             return true;
69         }
70
71         public static bool CanCreateInstanceUsingDefaultConstructor(Type type)
72         {
73             Fx.Assert(type != null, "type could not be null");
74
75             return type.IsValueType || (!type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null);
76         }
77
78         public static bool IsTypeCompatible(Type childObjectType, Type parentObjectType)
79         {
80             if (!parentObjectType.IsGenericTypeDefinition)
81             {
82                 return parentObjectType.IsAssignableFrom(childObjectType);
83             }
84             else if (parentObjectType.IsInterface)
85             {
86                 Type[] interfaceTypes = childObjectType.GetInterfaces();
87                 foreach (Type interfaceType in interfaceTypes)
88                 {
89                     if (interfaceType.IsGenericType)
90                     {
91                         if (interfaceType.GetGenericTypeDefinition() == parentObjectType)
92                         {
93                             return true;
94                         }
95                     }
96                 }
97
98                 return false;
99             }
100             else
101             {
102                 Type current = childObjectType;
103                 while (current != null)
104                 {
105                     if (current.IsGenericType)
106                     {
107                         if (current.GetGenericTypeDefinition() == parentObjectType)
108                         {
109                             return true;
110                         }
111                     }
112
113                     current = current.BaseType;
114                 }
115
116                 return false;
117             }
118         }
119
120         private static bool ContainsAnyFlag(GenericParameterAttributes attributes, GenericParameterAttributes flags)
121         {
122             return (attributes & flags) != GenericParameterAttributes.None;
123         }
124     }
125 }