Free cookie consent management tool by TermsFeed Policy Generator

source: branches/New Persistence Exploration/Persistence/Persistence/Default/Decomposers/EnumerableDecomposer.cs @ 1435

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

Properly deserialize enumerables with parent references, use single Setter delegate, fix id references of primitive values. (#506)

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