1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Reflection;
|
---|
4 | using System.Linq;
|
---|
5 |
|
---|
6 | namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable {
|
---|
7 |
|
---|
8 |
|
---|
9 | /// <summary>
|
---|
10 | /// Specifies which memebrs are selected for serialization by the StorableSerializer
|
---|
11 | /// </summary>
|
---|
12 | public enum StorableClassType {
|
---|
13 |
|
---|
14 | /// <summary>
|
---|
15 | /// Serialize the class completely empty
|
---|
16 | /// (ignore further [Storable] attributes inside the class)
|
---|
17 | /// </summary>
|
---|
18 | Empty,
|
---|
19 |
|
---|
20 | /// <summary>
|
---|
21 | /// Serialize only fields and properties that have been marked
|
---|
22 | /// with the [Storable] attribute
|
---|
23 | /// </summary>
|
---|
24 | MarkedOnly,
|
---|
25 |
|
---|
26 | /// <summary>
|
---|
27 | /// Serialize all fields but ignore the
|
---|
28 | /// [Storable] attribute on properties.
|
---|
29 | /// </summary>
|
---|
30 | [Obsolete("not implemented yet")]
|
---|
31 | AllFields,
|
---|
32 |
|
---|
33 | /// <summary>
|
---|
34 | /// Serialize all properties but ignore the
|
---|
35 | /// [Storable] attirbute on fields.
|
---|
36 | /// </summary>
|
---|
37 | [Obsolete("not implemented yet")]
|
---|
38 | AllProperties,
|
---|
39 |
|
---|
40 | /// <summary>
|
---|
41 | /// Serialize all fields and all properties
|
---|
42 | /// but ignore the [Storable] on all members.
|
---|
43 | /// </summary>
|
---|
44 | [Obsolete("not implemnted yet")]
|
---|
45 | AllFieldsAndAllProperties
|
---|
46 | };
|
---|
47 |
|
---|
48 |
|
---|
49 | /// <summary>
|
---|
50 | /// Mark a class to be considered by the <c>StorableSerializer</c>.
|
---|
51 | /// </summary>
|
---|
52 | [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
---|
53 | public sealed class StorableClassAttribute : Attribute {
|
---|
54 |
|
---|
55 |
|
---|
56 | /// <summary>
|
---|
57 | /// Specify how members are selected for serialization.
|
---|
58 | /// </summary>
|
---|
59 | public StorableClassType Type { get; set; }
|
---|
60 |
|
---|
61 | /// <summary>
|
---|
62 | /// Mark a class to be serialize by the <c>StorableSerizlier</c>
|
---|
63 | /// </summary>
|
---|
64 | public StorableClassAttribute(StorableClassType type) {
|
---|
65 | Type = type;
|
---|
66 | }
|
---|
67 |
|
---|
68 | /// <summary>
|
---|
69 | /// Check that the type is either empty i.e. has no fields or properties
|
---|
70 | /// or conatins proper parameterization through the storable attribute.
|
---|
71 | /// </summary>
|
---|
72 | /// <param name="type">The type.</param>
|
---|
73 | /// <param name="recusrive">if set to <c>true</c> recusrively checks class hierarchy.</param>
|
---|
74 | /// <returns>
|
---|
75 | /// <c>true</c> if the specified type is a storable type; otherwise, <c>false</c>.
|
---|
76 | /// </returns>
|
---|
77 | public static bool IsStorableType(Type type, bool recusrive) {
|
---|
78 | if (IsEmptyType(type, recusrive))
|
---|
79 | return true;
|
---|
80 | StorableClassAttribute attribute = type
|
---|
81 | .GetCustomAttributes(typeof(StorableClassAttribute), false)
|
---|
82 | .Cast<StorableClassAttribute>().SingleOrDefault();
|
---|
83 | if (attribute == null)
|
---|
84 | return false;
|
---|
85 | if (!recusrive || type.BaseType == null)
|
---|
86 | return true;
|
---|
87 | else
|
---|
88 | return IsStorableType(type.BaseType, true);
|
---|
89 | }
|
---|
90 |
|
---|
91 | private const BindingFlags allDeclaredMembers =
|
---|
92 | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
|
---|
93 |
|
---|
94 |
|
---|
95 | /// <summary>
|
---|
96 | /// Determines whether the specified type has no fields or properties except
|
---|
97 | /// readonly properties or constant fields.
|
---|
98 | /// </summary>
|
---|
99 | /// <param name="type">The type.</param>
|
---|
100 | /// <param name="recursive">if set to <c>true</c> recursively check class hierarchy.</param>
|
---|
101 | /// <returns>
|
---|
102 | /// <c>true</c> if the specified type is empty; otherwise, <c>false</c>.
|
---|
103 | /// </returns>
|
---|
104 | public static bool IsEmptyType(Type type, bool recursive) {
|
---|
105 | foreach (MemberInfo memberInfo in type.GetMembers(allDeclaredMembers)) {
|
---|
106 | if (
|
---|
107 | memberInfo.MemberType == MemberTypes.Field && IsModifiableField((FieldInfo)memberInfo) ||
|
---|
108 | memberInfo.MemberType == MemberTypes.Property && IsModifiableProperty((PropertyInfo)memberInfo)) {
|
---|
109 | return false;
|
---|
110 | }
|
---|
111 | }
|
---|
112 | if (!recursive || type.BaseType == null)
|
---|
113 | return true;
|
---|
114 | else
|
---|
115 | return IsEmptyType(type.BaseType, true);
|
---|
116 | }
|
---|
117 |
|
---|
118 | private static bool IsModifiableField(FieldInfo fi) {
|
---|
119 | return !fi.IsLiteral && !fi.IsInitOnly;
|
---|
120 | }
|
---|
121 |
|
---|
122 | private static bool IsModifiableProperty(PropertyInfo pi) {
|
---|
123 | return pi.CanWrite;
|
---|
124 | }
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 |
|
---|
129 |
|
---|