Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/Decomposers/EnumerableDecomposer.cs @ 1539

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

Add Priority property to IDecomposer interface to allow specialized decomposers to be tried first. (#578)

File size: 2.3 KB
Line 
1using System;
2using System.Collections;
3using System.Reflection;
4using HeuristicLab.Persistence.Core;
5using HeuristicLab.Persistence.Interfaces;
6using System.Collections.Generic;
7
8namespace HeuristicLab.Persistence.Default.Decomposers {
9
10  public class EnumerableCache {
11    readonly List<object> values;
12    int nSet;
13    int count;
14    readonly object enumerable;
15    readonly MethodInfo addMethod;
16
17    public EnumerableCache(object enumerable, MethodInfo addMethod) {     
18      values = new List<object>();
19      this.enumerable = enumerable;
20      this.addMethod = addMethod;
21      count = -1;
22    }
23
24    public Setter GetNextSetter() {     
25      int index = values.Count;     
26      values.Add(new object());
27      return v => Set(index, v);
28    }
29
30    private void Set(int index, object value) {     
31      values[index] = value;
32      nSet += 1;
33      if (count >= 0 && nSet >= count)
34        Fill();
35    }
36
37    public void Terminate() {
38      count = values.Count;     
39      if (nSet >= count)
40        Fill();
41    }
42
43    private void Fill() {     
44      foreach ( object v in values ) {
45        addMethod.Invoke(enumerable, new[] {v});
46      }
47    }
48
49  }
50
51  public class EnumerableDecomposer : IDecomposer {
52
53    public int Priority {
54      get { return 100; }
55    }
56
57
58    public bool CanDecompose(Type type) {
59      return
60        type.GetInterface(typeof(IEnumerable).FullName) != null &&
61        type.GetMethod("Add") != null &&
62        type.GetMethod("Add").GetParameters().Length == 1 &&
63        type.GetConstructor(
64          BindingFlags.Public |
65          BindingFlags.NonPublic |
66          BindingFlags.Instance,
67          null, Type.EmptyTypes, null) != null;
68    }
69
70    public IEnumerable<Tag> DeCompose(object obj) {
71      foreach (object o in (IEnumerable)obj) {
72        yield return new Tag(null, o);
73      }
74    }
75
76    public object CreateInstance(Type type) {
77      return Activator.CreateInstance(type, true);
78    }
79
80    public object Populate(object instance, IEnumerable<Tag> tags, Type type) {
81      MethodInfo addMethod = type.GetMethod("Add");
82      EnumerableCache cache = new EnumerableCache(instance, addMethod);
83      foreach (var tag in tags) {
84        tag.SafeSet(cache.GetNextSetter());
85      }
86      cache.Terminate();
87      return instance;
88    }
89
90  } 
91
92}
Note: See TracBrowser for help on using the repository browser.