1 | using System;
|
---|
2 | using System.Collections;
|
---|
3 | using System.Reflection;
|
---|
4 | using HeuristicLab.Persistence.Core;
|
---|
5 | using HeuristicLab.Persistence.Interfaces;
|
---|
6 | using System.Collections.Generic;
|
---|
7 |
|
---|
8 | namespace HeuristicLab.Persistence.Default.Decomposers {
|
---|
9 |
|
---|
10 | public abstract class EnumerableDecomposer : IDecomposer {
|
---|
11 |
|
---|
12 | public abstract void PerformAdd(object instance, MethodInfo addMethod, Tag tag);
|
---|
13 |
|
---|
14 | public bool CanDecompose(Type type) {
|
---|
15 | return
|
---|
16 | type.GetInterface(typeof(IEnumerable).FullName) != null &&
|
---|
17 | type.GetMethod("Add") != null &&
|
---|
18 | type.GetMethod("Add").GetParameters().Length == 1 &&
|
---|
19 | type.GetConstructor(
|
---|
20 | BindingFlags.Public |
|
---|
21 | BindingFlags.NonPublic |
|
---|
22 | BindingFlags.Instance,
|
---|
23 | null, Type.EmptyTypes, null) != null;
|
---|
24 | }
|
---|
25 |
|
---|
26 | public IEnumerable<Tag> DeCompose(object obj) {
|
---|
27 | foreach (object o in (IEnumerable)obj) {
|
---|
28 | yield return new Tag(null, o);
|
---|
29 | }
|
---|
30 | }
|
---|
31 |
|
---|
32 | public object CreateInstance(Type type) {
|
---|
33 | return Activator.CreateInstance(type, true);
|
---|
34 | }
|
---|
35 |
|
---|
36 | public object Populate(object instance, IEnumerable<Tag> tags, Type type) {
|
---|
37 | MethodInfo addMethod = type.GetMethod("Add");
|
---|
38 | foreach (var tag in tags) {
|
---|
39 | PerformAdd(instance, addMethod, tag);
|
---|
40 | }
|
---|
41 | return instance;
|
---|
42 | }
|
---|
43 |
|
---|
44 | }
|
---|
45 |
|
---|
46 | /// <summary>
|
---|
47 | /// Does never re-order elements but cannot reconstruct enumerables that directly
|
---|
48 | /// or indirectly contain references to not-yet-contructed parent objects (e.g. arrays).
|
---|
49 | /// </summary>
|
---|
50 | public class SafeEnumerableDecomposer : EnumerableDecomposer {
|
---|
51 | public override void PerformAdd(object instance, MethodInfo addMethod, Tag tag) {
|
---|
52 | addMethod.Invoke(instance, new[] { tag.Value });
|
---|
53 | }
|
---|
54 | }
|
---|
55 | /// <summary>
|
---|
56 | /// May re-order elements if the enumerable contains references to
|
---|
57 | /// not-yet-constructed parent objects (e.g. arrays).
|
---|
58 | /// </summary>
|
---|
59 | public class RobustEnumerableDecomposer : EnumerableDecomposer {
|
---|
60 | public override void PerformAdd(object instance, MethodInfo addMethod, Tag tag) {
|
---|
61 | tag.SafeSet((value) => addMethod.Invoke(instance, new[] { value }));
|
---|
62 | }
|
---|
63 | }
|
---|
64 |
|
---|
65 | }
|
---|