Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/30/15 15:12:34 (8 years ago)
Author:
mkommend
Message:

#2521: Adapted type discovery and type selector to allow the creation of generic programmable problems.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ProblemRefactoring/HeuristicLab.PluginInfrastructure/3.3/TypeExtensions.cs

    r12012 r13422  
    7676    }
    7777
    78     internal static bool IsSubTypeOf(this Type subType, Type baseType) {
     78    internal static bool IsAssignableTo(this Type subType, Type baseType) {
    7979      if (baseType.IsAssignableFrom(subType)) return true;
     80
     81      //check generics
    8082      if (!baseType.IsGenericType) return false;
     83      if (RecursiveCheckGenericTypes(baseType, subType)) return true;
    8184
    82       if (RecursiveCheckGenericTypes(baseType, subType)) return true;
     85      //check generic interfaces
    8386      IEnumerable<Type> implementedInterfaces = subType.GetInterfaces().Where(t => t.IsGenericType);
    84       foreach (var implementedInterface in implementedInterfaces.Where(i => i.IsGenericType)) {
    85         if (baseType.CheckGenericTypes(implementedInterface)) return true;
    86       }
    87 
    88       return false;
     87      return implementedInterfaces.Any(implementedInterface => baseType.CheckGenericTypes(implementedInterface));
    8988    }
    9089
    9190    private static bool RecursiveCheckGenericTypes(Type baseType, Type subType) {
    9291      if (!baseType.IsGenericType) return false;
    93       if (!subType.IsGenericType) return false;
    94       if (baseType.CheckGenericTypes(subType)) return true;
     92      if (subType.IsGenericType && baseType.CheckGenericTypes(subType)) return true;
    9593      if (subType.BaseType == null) return false;
    9694
     
    102100      var subTypeGenericTypeDefinition = subType.GetGenericTypeDefinition();
    103101      if (baseTypeGenericTypeDefinition != subTypeGenericTypeDefinition) return false;
     102
    104103      var baseTypeGenericArguments = baseType.GetGenericArguments();
    105104      var subTypeGenericArguments = subType.GetGenericArguments();
     
    109108        var subTypeGenericArgument = subTypeGenericArguments[i];
    110109
    111         if (baseTypeGenericArgument.IsGenericParameter ^ subTypeGenericArgument.IsGenericParameter) return false;
    112         if (baseTypeGenericArgument == subTypeGenericArgument) continue;
    113         if (!baseTypeGenericArgument.IsGenericParameter && !subTypeGenericArgument.IsGenericParameter) return false;
     110        //no generic parameters => concrete types => check for type equality (ignore co- and contravariance)
     111        //for example List<int> is only a List<int>, IParameter<IItem> is not a base type of IParameter<DoubleValue>
     112        if (!baseTypeGenericArgument.IsGenericParameter && !subTypeGenericArgument.IsGenericParameter) {
     113          if (baseTypeGenericArgument == subTypeGenericArgument) continue;
     114          return false;
     115        }
    114116
    115         if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint) &&
    116             !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) return false;
    117         if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) &&
    118             !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) return false;
    119         if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint) &&
    120             !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) return false;
     117        //baseTypeGenericArgument is a concrete type and the subTypeGenericArgument is a generic parameter
     118        //for example List<int> is not a base type of List<T>
     119        if (!baseTypeGenericArgument.IsGenericParameter && subTypeGenericArgument.IsGenericParameter) return false;
    121120
    122         foreach (var baseTypeGenericParameterConstraint in baseTypeGenericArgument.GetGenericParameterConstraints()) {
    123           if (!subTypeGenericArgument.GetGenericParameterConstraints().Any(t => baseTypeGenericParameterConstraint.IsAssignableFrom(t))) return false;
     121        //baseTypeGenericArugment is a generic parameter and the subTypeGenericArgument is a concrete type => check type constraints
     122        //for example IParameter<T> is a base type of IParameter<IItem> if all generic contraints on T are fulfilled
     123        if (baseTypeGenericArgument.IsGenericParameter && !subTypeGenericArgument.IsGenericParameter) {
     124          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint) &&
     125            subTypeGenericArgument.IsValueType) return false;
     126          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) &&
     127            subTypeGenericArgument.GetConstructor(Type.EmptyTypes) == null) return false;
     128          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) {
     129            if (!subTypeGenericArgument.IsValueType) return false;
     130            if (subTypeGenericArgument.IsGenericType && subTypeGenericArgument.GetGenericTypeDefinition() == typeof(Nullable<>))
     131              return false;
     132          }
     133
     134          //not assignable if the subTypeGenericArgument is not assignable to all of the constraints of the base type
     135          if (baseTypeGenericArgument.GetGenericParameterConstraints().Any(baseTypeGenericParameterConstraint =>
     136            !baseTypeGenericParameterConstraint.IsAssignableFrom(subTypeGenericArgument)))
     137            return false;
     138        }
     139
     140        //both generic arguments are generic parameters => check type constraints
     141        //for example IParameter<T> is a base type of IParameter<T>
     142        if (baseTypeGenericArgument.IsGenericParameter && subTypeGenericArgument.IsGenericParameter) {
     143          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint) &&
     144              !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) return false;
     145          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) &&
     146              !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) return false;
     147          if (baseTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint) &&
     148              !subTypeGenericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) return false;
     149
     150          //not assignable if any of the constraints is not assignable to the constraints of the base type
     151          if (baseTypeGenericArgument.GetGenericParameterConstraints().Any(baseTypeGenericParameterConstraint => !subTypeGenericArgument.GetGenericParameterConstraints().Any(t => baseTypeGenericParameterConstraint.IsAssignableFrom(t)))) {
     152            return false;
     153          }
    124154        }
    125155      }
Note: See TracChangeset for help on using the changeset viewer.