Changeset 2724


Ignore:
Timestamp:
01/29/10 16:27:44 (10 years ago)
Author:
mkommend
Message:

corrected handling of generic content types (ticket #857)

Location:
trunk/sources/HeuristicLab.MainForm/3.2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.MainForm/3.2/ContentAttribute.cs

    r2696 r2724  
    6060             select a.type;
    6161    }
     62
     63    internal static IEnumerable<Type> GetViewableTypes(Type viewType) {
     64      ContentAttribute[] attributes = (ContentAttribute[])viewType.GetCustomAttributes(typeof(ContentAttribute), false);
     65      return from a in attributes
     66             select a.type;
     67    }
    6268  }
    6369}
  • trunk/sources/HeuristicLab.MainForm/3.2/MainFormManager.cs

    r2702 r2724  
    7676
    7777    public static IEnumerable<Type> GetViewTypes(Type contentType) {
    78       return from v in views
    79              where ContentAttribute.CanViewType(v, contentType)
    80              select v;
     78      List<Type> viewTypes = (from v in views
     79                              where ContentAttribute.CanViewType(v, contentType)
     80                              select v).ToList();
     81      //transform generic type definitions to generic types
     82      for (int i = 0; i < viewTypes.Count; i++) {
     83        viewTypes[i] = TransformGenericTypeDefinition(viewTypes[i], contentType);
     84      }
     85      return viewTypes;
    8186    }
    8287
     
    9398      Type type = contentType;
    9499      while (type != null) {
    95         foreach (Type defaultViewType in defaultViews.Keys) {
    96           if (type == defaultViewType || type.CheckGenericTypes(defaultViewType))
    97             return defaultViews[defaultViewType];
     100        foreach (Type defaultContentType in defaultViews.Keys) {
     101          if (type == defaultContentType || type.CheckGenericTypes(defaultContentType))
     102            return TransformGenericTypeDefinition(defaultViews[defaultContentType], contentType);
    98103        }
    99104        type = type.BaseType;
     
    105110                         select t).ToList();
    106111      if (temp.Count == 1)
    107         return defaultViews[temp[0]];
     112        return TransformGenericTypeDefinition(defaultViews[temp[0]], contentType);
    108113      //more than one default view for implemented interfaces are found
    109114      if (temp.Count > 1)
     
    117122        return null;
    118123
    119       Type viewType = TransformGenericTypeDefinition(t, objectToView);
    120       if (viewType == null)
    121         return null;
    122 
    123       return (IView)Activator.CreateInstance(viewType, objectToView);
     124      return (IView)Activator.CreateInstance(t, objectToView);
    124125    }
    125126
     
    136137      if (!typeof(IView).IsAssignableFrom(viewType))
    137138        throw new ArgumentException("View can not be created becaues given type " + viewType.ToString() + " is not of type IView.");
     139      if (viewType.IsGenericTypeDefinition)
     140        throw new ArgumentException("View can not be created becaues given type " + viewType.ToString() + " is a generic type definition.");
    138141
    139       Type t = TransformGenericTypeDefinition(viewType, objectToView);
    140       if (t == null)
    141         return null;
    142 
    143       return (IView)Activator.CreateInstance(t, objectToView);
     142      return (IView)Activator.CreateInstance(viewType, objectToView);
    144143    }
    145144
    146     private static Type TransformGenericTypeDefinition(Type type, object objectToView) {
    147       if (!type.IsGenericTypeDefinition)
    148         return type;
     145    private static Type TransformGenericTypeDefinition(Type viewType, Type contentType) {
     146      if (contentType.IsGenericTypeDefinition)
     147        throw new ArgumentException("The content type " + contentType.ToString() + " must not be a generic type definition.");
    149148
    150       Type[] typeGenericArguments = type.GetGenericArguments();
    151       Type[] objectGenericArguments = objectToView.GetType().GetGenericArguments();
     149      if (!viewType.IsGenericTypeDefinition)
     150        return viewType;
    152151
    153       for (int i = 0; i < typeGenericArguments.Length; i++) {
    154         foreach (Type typeConstraint in typeGenericArguments[i].GetGenericParameterConstraints()) {
    155           if (!typeConstraint.IsAssignableFrom(objectGenericArguments[i]))
     152      Type contentTypeBaseType = contentType;
     153      foreach (Type type in ContentAttribute.GetViewableTypes(viewType)) {
     154        while (contentTypeBaseType != null && (!contentTypeBaseType.IsGenericType ||
     155              type.GetGenericTypeDefinition() != contentTypeBaseType.GetGenericTypeDefinition()))
     156          contentTypeBaseType = contentTypeBaseType.BaseType;
     157
     158        //check interfaces for generic type arguments
     159        if (contentTypeBaseType == null) {
     160          IEnumerable<Type> implementedInterfaces = contentType.GetInterfaces().Where(t => t.IsGenericType);
     161          foreach (Type implementedInterface in implementedInterfaces) {
     162            if (implementedInterface.CheckGenericTypes(viewType))
     163              contentTypeBaseType = implementedInterface;
     164          }
     165        }
     166      }
     167
     168      if (!contentTypeBaseType.IsGenericType)
     169        throw new ArgumentException("Neither content type itself nor any of its base classes is a generic type. Could not determine generic type argument for the view.");
     170
     171      Type[] viewTypeGenericArguments = viewType.GetGenericArguments();
     172      Type[] contentTypeGenericArguments = contentTypeBaseType.GetGenericArguments();
     173
     174      if (contentTypeGenericArguments.Length != viewTypeGenericArguments.Length)
     175        throw new ArgumentException("Neiter the type (" + contentType.ToString() + ") nor any of its base types specifies " +
     176          viewTypeGenericArguments.Length + " generic type arguments.");
     177
     178      for (int i = 0; i < viewTypeGenericArguments.Length; i++) {
     179        foreach (Type typeConstraint in viewTypeGenericArguments[i].GetGenericParameterConstraints()) {
     180          if (!typeConstraint.IsAssignableFrom(contentTypeGenericArguments[i]))
    156181            return null;
    157182        }
    158183      }
    159184
    160       Type t = type.MakeGenericType(objectToView.GetType().GetGenericArguments());
    161       return t;
     185      Type returnType = viewType.MakeGenericType(contentTypeGenericArguments);
     186      return returnType;
    162187    }
    163188  }
  • trunk/sources/HeuristicLab.MainForm/3.2/TypeExtension.cs

    r2696 r2724  
    3232        return true;
    3333
    34       if (type.IsGenericType && other.IsGenericType) {
    35         if (recursiveCheckGenericTypes(type, other))
     34      if (recursiveCheckGenericTypes(type, other))
     35        return true;
     36
     37      IEnumerable<Type> implementedInterfaces = type.GetInterfaces().Where(t => t.IsGenericType);
     38      foreach (Type implementedInterface in implementedInterfaces) {
     39        if (implementedInterface.CheckGenericTypes(other))
    3640          return true;
     41      }
    3742
    38         IEnumerable<Type> implementedInterfaces = type.GetInterfaces().Where(t => t.IsGenericType);
    39         foreach (Type implementedInterface in implementedInterfaces) {
    40           if (implementedInterface.CheckGenericTypes(other))
    41             return true;
    42         }
    43       }
    4443      return false;
    4544    }
     
    7978      return true;
    8079    }
     80
     81    internal static Type[] ExtractGenericTypeArguments(this Type type, Type other) {
     82      Type[] types = new Type[0];
     83      return types;
     84    }
    8185  }
    8286}
Note: See TracChangeset for help on using the changeset viewer.