Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/Decomposers/NumberEnumerable2StringDecomposer.cs @ 1567

Last change on this file since 1567 was 1567, checked in by epitzer, 15 years ago

One file per class; rename ViewOnlyFormat -> DebugStringFormat (#548)

File size: 3.6 KB
Line 
1using System;
2using HeuristicLab.Persistence.Interfaces;
3using HeuristicLab.Persistence.Core;
4using System.Collections.Generic;
5using System.Reflection;
6using System.Globalization;
7using System.Text;
8
9namespace HeuristicLab.Persistence.Default.Decomposers {
10
11  [EmptyStorableClass]
12  public class NumberEnumerable2StringDecomposer : IDecomposer {
13
14    public int Priority {
15      get { return 200; }
16    }
17
18    private static readonly Number2StringConverter numberConverter =
19      new Number2StringConverter();
20
21    private static readonly Dictionary<Type, Type> interfaceCache = new Dictionary<Type, Type>();
22
23    public Type GetGenericEnumerableInterface(Type type) {
24      if (interfaceCache.ContainsKey(type))
25        return interfaceCache[type];
26      foreach (Type iface in type.GetInterfaces()) {
27        if (iface.IsGenericType &&
28          iface.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
29          numberConverter.CanDecompose(iface.GetGenericArguments()[0])) {
30          interfaceCache.Add(type, iface);
31          return iface;
32        }
33      }
34      interfaceCache.Add(type, null);
35      return null;
36    }
37
38    public bool ImplementsGenericEnumerable(Type type) {
39      return GetGenericEnumerableInterface(type) != null;
40    }
41
42    public bool HasAddMethod(Type type) {
43      return
44        type.GetMethod("Add") != null &&
45        type.GetMethod("Add").GetParameters().Length == 1 &&
46        type.GetConstructor(
47          BindingFlags.Public |
48          BindingFlags.NonPublic |
49          BindingFlags.Instance,
50          null, Type.EmptyTypes, null) != null;
51    }
52
53    public bool CanDecompose(Type type) {
54      return
55        ImplementsGenericEnumerable(type) &&
56        HasAddMethod(type);
57    }
58
59    public IEnumerable<Tag> CreateMetaInfo(object o) {
60      return new Tag[] { };
61    }
62
63    public IEnumerable<Tag> Decompose(object obj) {
64      Type type = obj.GetType();
65      Type enumerable = GetGenericEnumerableInterface(type);
66      InterfaceMapping iMap = obj.GetType().GetInterfaceMap(enumerable);
67      MethodInfo getEnumeratorMethod =
68        iMap.TargetMethods[
69        Array.IndexOf(
70          iMap.InterfaceMethods,
71          enumerable.GetMethod("GetEnumerator"))];
72      object[] empty = new object[] { };
73      object genericEnumerator = getEnumeratorMethod.Invoke(obj, empty);
74      MethodInfo moveNextMethod = genericEnumerator.GetType().GetMethod("MoveNext");
75      PropertyInfo currentProperty = genericEnumerator.GetType().GetProperty("Current");
76      StringBuilder sb = new StringBuilder();
77      while ((bool)moveNextMethod.Invoke(genericEnumerator, empty))
78        sb.Append(
79          numberConverter.Format(
80            currentProperty.GetValue(genericEnumerator, null))).Append(';');
81      yield return new Tag("compact enumerable", sb.ToString());
82    }
83
84    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
85      return Activator.CreateInstance(type, true);
86    }
87
88    public void Populate(object instance, IEnumerable<Tag> tags, Type type) {
89      Type enumerable = GetGenericEnumerableInterface(type);
90      Type elementType = enumerable.GetGenericArguments()[0];
91      MethodInfo addMethod = type.GetMethod("Add");
92      var tagEnumerator = tags.GetEnumerator();
93      tagEnumerator.MoveNext();
94      string[] stringValues = ((string)tagEnumerator.Current.Value)
95        .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
96      foreach (var value in stringValues) {
97        addMethod.Invoke(instance, new[] { numberConverter.Parse(value, elementType) });
98      }
99    }
100  }
101}
Note: See TracBrowser for help on using the repository browser.