Changeset 1514


Ignore:
Timestamp:
04/03/09 15:09:06 (12 years ago)
Author:
epitzer
Message:

Improved 2string decomposers. (#563)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Persistence/Default/Decomposers/X2StringDecomposer.cs

    r1494 r1514  
    66using System.Globalization;
    77using System.Text;
    8 using System.Collections;
    98
    109namespace HeuristicLab.Persistence.Default.Decomposers {
     
    2827      };
    2928
    30     private static readonly Dictionary<Type, MethodInfo> numberParser
     29    private static readonly Dictionary<Type, MethodInfo> numberParsers
    3130
    3231    static Number2StringDecomposer() {
    33       numberParser = new Dictionary<Type, MethodInfo>();
     32      numberParsers = new Dictionary<Type, MethodInfo>();
    3433      foreach ( var type in numberTypes ) {
    35         numberParser[type] = type
     34        numberParsers[type] = type
    3635          .GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
    3736                     null, new[] {typeof (string)}, null);         
     
    4039
    4140    public bool CanDecompose(Type type) {
    42       return numberParser.ContainsKey(type);
    43     }
    44 
    45     public string SimpleDecompose(object obj) {
     41      return numberParsers.ContainsKey(type);
     42    }
     43
     44    public string Format(object obj) {
    4645      if (obj.GetType() == typeof(float))       
    4746        return ((float)obj).ToString("r", CultureInfo.InvariantCulture);
    48       else if (obj.GetType() == typeof(double))
     47      if (obj.GetType() == typeof(double))
    4948        return ((double)obj).ToString("r", CultureInfo.InvariantCulture);
    50       else if (obj.GetType() == typeof(decimal))
     49      if (obj.GetType() == typeof(decimal))
    5150        return ((decimal)obj).ToString("r", CultureInfo.InvariantCulture);
    52       else
    53         return obj.ToString();     
     51      return obj.ToString();
    5452    }
    5553
    5654    public IEnumerable<Tag> DeCompose(object obj) {     
    57       yield return new Tag(SimpleDecompose(obj));     
     55      yield return new Tag(Format(obj));     
    5856    }
    5957
     
    6361
    6462    public object Parse(string stringValue, Type type) {
    65       return numberParser[type]
     63      return numberParsers[type]
    6664        .Invoke(null,
    6765            BindingFlags.Static | BindingFlags.PutRefDispProperty,
     
    120118        sb.Append(a.GetLowerBound(i)).Append(';');
    121119      foreach (var number in a) {       
    122         sb.Append(numberDecomposer.SimpleDecompose(number)).Append(';');
     120        sb.Append(numberDecomposer.Format(number)).Append(';');
    123121      }
    124122      yield return new Tag("compact array", sb.ToString());
     
    130128
    131129    public object Populate(object instance, IEnumerable<Tag> tags, Type type) {     
    132       var iter = tags.GetEnumerator();
    133       iter.MoveNext();
    134       var it = ((string) iter.Current.Value).Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries).GetEnumerator();
    135       it.MoveNext();
    136       int rank = int.Parse((string) it.Current);
    137       it.MoveNext();
     130      var tagIter = tags.GetEnumerator();
     131      tagIter.MoveNext();
     132      var valueIter = ((string) tagIter.Current.Value)
     133        .Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries)
     134        .GetEnumerator();
     135      valueIter.MoveNext();
     136      int rank = int.Parse((string) valueIter.Current);     
    138137      int[] lengths = new int[rank];
    139       int[] lowerBounds = new int[rank];
    140       for (int i = 0; i < rank; i++, it.MoveNext())
    141         lengths[i] = int.Parse((string) it.Current);
    142       for (int i = 0; i < rank; i++, it.MoveNext())
    143         lowerBounds[i] = int.Parse((string)it.Current);
    144       Array a = Array.CreateInstance(type.GetElementType(), lengths, lowerBounds);
     138      int[] lowerBounds = new int[rank];     
     139      for (int i = 0; i < rank; i++) {
     140        valueIter.MoveNext();
     141        lengths[i] = int.Parse((string) valueIter.Current);       
     142      }     
     143      for (int i = 0; i < rank; i++) {
     144        valueIter.MoveNext();
     145        lowerBounds[i] = int.Parse((string) valueIter.Current);       
     146      }
     147      Type elementType = type.GetElementType();
     148      Array a = Array.CreateInstance(elementType, lengths, lowerBounds);
    145149      int[] positions = (int[]) lowerBounds.Clone();
    146       while (it.MoveNext()) {
     150      while (valueIter.MoveNext()) {
    147151        a.SetValue(
    148           numberDecomposer.Parse((string)it.Current, type.GetElementType()),         
     152          numberDecomposer.Parse((string)valueIter.Current, elementType),         
    149153          positions);
    150154        positions[0] += 1;
     
    167171      new Number2StringDecomposer();
    168172   
     173    private static readonly Dictionary<Type, Type> interfaceCache = new Dictionary<Type, Type>();
     174
     175    public Type GetGenericEnumerableInterface(Type type) {
     176      if (interfaceCache.ContainsKey(type))
     177        return interfaceCache[type];
     178      foreach (Type iface in type.GetInterfaces()) {
     179        if (iface.IsGenericType &&
     180          iface.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
     181          numberDecomposer.CanDecompose(iface.GetGenericArguments()[0])) {
     182          interfaceCache.Add(type, iface);
     183          return iface;
     184        }
     185      }
     186      interfaceCache.Add(type, null);
     187      return null;
     188    }
     189   
    169190    public bool ImplementsGenericEnumerable(Type type) {
    170       foreach( Type iface in type.GetInterfaces() ) {
    171         if ( iface.IsGenericType &&
    172           iface.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
    173           numberDecomposer.CanDecompose(iface.GetGenericArguments()[0]) )
    174           return true;
    175       }
    176       return false;
     191      return GetGenericEnumerableInterface(type) != null;
    177192    }
    178193
     
    195210
    196211    public IEnumerable<Tag> DeCompose(object obj) {
    197       Type elementType = obj.GetType().GetGenericArguments()[0];
    198       Type instantiatedGenericInterface =
    199         typeof (IEnumerable<>).MakeGenericType(new[] {elementType});
    200       MethodInfo genericGetEnumeratorMethod =
    201         instantiatedGenericInterface.GetMethod("GetEnumerator");
    202       InterfaceMapping iMap = obj.GetType().GetInterfaceMap(instantiatedGenericInterface);
     212      Type type = obj.GetType();
     213      Type enumerable = GetGenericEnumerableInterface(type);     
     214      InterfaceMapping iMap = obj.GetType().GetInterfaceMap(enumerable);     
    203215      MethodInfo getEnumeratorMethod =
    204         iMap.TargetMethods[Array.IndexOf(iMap.InterfaceMethods, genericGetEnumeratorMethod)];
     216        iMap.TargetMethods[
     217        Array.IndexOf(
     218          iMap.InterfaceMethods,
     219          enumerable.GetMethod("GetEnumerator"))];
    205220      object[] empty = new object[] {};
    206221      object genericEnumerator = getEnumeratorMethod.Invoke(obj, empty);
     
    210225      while ( (bool)moveNextMethod.Invoke(genericEnumerator, empty) )
    211226        sb.Append(
    212           numberDecomposer.SimpleDecompose(
     227          numberDecomposer.Format(
    213228            currentProperty.GetValue(genericEnumerator, null))).Append(';');
    214229      yield return new Tag("compact enumerable", sb.ToString());
     
    220235
    221236    public object Populate(object instance, IEnumerable<Tag> tags, Type type) {
    222       Type elementType = type.GetGenericArguments()[0];
     237      Type enumerable = GetGenericEnumerableInterface(type);
     238      Type elementType = enumerable.GetGenericArguments()[0];     
    223239      MethodInfo addMethod = type.GetMethod("Add");     
    224240      var tagEnumerator = tags.GetEnumerator();
Note: See TracChangeset for help on using the changeset viewer.