Changeset 3029
- Timestamp:
- 03/15/10 12:02:00 (15 years ago)
- Location:
- trunk/sources/HeuristicLab.Persistence/3.3
- Files:
-
- 3 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableClassAttribute.cs
r3025 r3029 4 4 using System.Linq; 5 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 only fields and properties that have been marked 16 /// with the [Storable] attribute. This is the default value. 17 /// </summary> 18 MarkedOnly, 19 20 /// <summary> 21 /// Serialize all fields but ignore the 22 /// [Storable] attribute on properties. 23 /// </summary> 24 [Obsolete("not implemented yet")] 25 AllFields, 26 27 /// <summary> 28 /// Serialize all properties but ignore the 29 /// [Storable] attirbute on fields. 30 /// </summary> 31 [Obsolete("not implemented yet")] 32 AllProperties, 33 34 /// <summary> 35 /// Serialize all fields and all properties 36 /// but ignore the [Storable] on all members. 37 /// </summary> 38 [Obsolete("not implemnted yet")] 39 AllFieldsAndAllProperties 40 }; 41 6 namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable { 42 7 43 8 /// <summary> -
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs
r3025 r3029 12 12 /// <summary> 13 13 /// Intended for serialization of all custom classes. Classes should have the 14 /// <c>[StorableClass]</c> attribute set and a serialization mode set. 15 /// Optionally selected fields and properties can be marked with the 16 /// <c>[Storable]</c> attribute. 14 /// <c>[StorableClass]</c> attribute set. The default mode is to serialize 15 /// members with the <c>[Storable]</c> attribute set. Alternatively the 16 /// storable mode can be set to <c>AllFields</c>, <c>AllProperties</c> 17 /// or <c>AllFieldsAndAllProperties</c>. 17 18 /// </summary> 18 [StorableClass] 19 [StorableClass] 19 20 public class StorableSerializer : ICompositeSerializer { 20 21 21 22 22 #region ICompositeSerializer implementation … … 30 30 GetStorableConstructor(type) == null) 31 31 return false; 32 return IsEmptyOrStorableType(type, true);32 return StorableReflection.IsEmptyOrStorableType(type, true); 33 33 } 34 34 … … 37 37 GetStorableConstructor(type) == null) 38 38 return "no default constructor and no storable constructor"; 39 if (! IsEmptyOrStorableType(type, true))39 if (!StorableReflection.IsEmptyOrStorableType(type, true)) 40 40 return "class is not marked with the storable class attribute"; 41 41 return "no reason"; … … 71 71 while (iter.MoveNext()) { 72 72 memberDict.Add(iter.Current.Name, iter.Current); 73 } 73 } 74 74 foreach (var accessor in GetStorableAccessors(instance)) { 75 75 if (memberDict.ContainsKey(accessor.Name)) { … … 84 84 #endregion 85 85 86 #region constan ces & private data types86 #region constants & private data types 87 87 88 88 private const BindingFlags ALL_CONSTRUCTORS = 89 89 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 90 91 private const BindingFlags DECLARED_INSTANCE_MEMBERS =92 BindingFlags.Instance |93 BindingFlags.Public |94 BindingFlags.NonPublic |95 BindingFlags.DeclaredOnly;96 97 private sealed class StorableMemberInfo {98 public StorableAttribute Attribute { get; private set; }99 public MemberInfo MemberInfo { get; private set; }100 public string DisentangledName { get; private set; }101 public string FullyQualifiedMemberName {102 get {103 return new StringBuilder()104 .Append(MemberInfo.ReflectedType.FullName)105 .Append('.')106 .Append(MemberInfo.Name)107 .ToString();108 }109 }110 public StorableMemberInfo(StorableAttribute attribute, MemberInfo memberInfo) {111 this.Attribute = attribute;112 this.MemberInfo = memberInfo;113 }114 public override string ToString() {115 return new StringBuilder()116 .Append('[').Append(Attribute).Append(", ")117 .Append(MemberInfo).Append('}').ToString();118 }119 public void SetDisentangledName(string name) {120 DisentangledName = Attribute.Name ?? name;121 }122 public Type GetPropertyDeclaringBaseType() {123 return ((PropertyInfo)MemberInfo).GetGetMethod(true).GetBaseDefinition().DeclaringType;124 }125 }126 90 127 91 private sealed class TypeQuery { … … 141 105 142 106 private MemberCache storableMemberCache = new MemberCache(); 143 private Dictionary<Type, ConstructorInfo> constructorCache = 107 private Dictionary<Type, ConstructorInfo> constructorCache = 144 108 new Dictionary<Type, ConstructorInfo>(); 145 109 146 110 #endregion 147 111 148 #region a uxiliary attribute reflection tools112 #region attribute access 149 113 150 114 private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type) { … … 157 121 if (storableMemberCache.ContainsKey(query)) 158 122 return storableMemberCache[query]; 159 var storablesMembers = GenerateStorableMembers(type, inherited);123 var storablesMembers = StorableReflection.GenerateStorableMembers(type, inherited); 160 124 storableMemberCache[query] = storablesMembers; 161 125 return storablesMembers; 162 126 } 163 } 164 165 private static IEnumerable<StorableMemberInfo> GenerateStorableMembers(Type type, bool inherited) { 166 var storableMembers = new List<StorableMemberInfo>(); 167 if (inherited && type.BaseType != null) 168 storableMembers.AddRange(GenerateStorableMembers(type.BaseType, true)); 169 foreach (MemberInfo memberInfo in type.GetMembers(DECLARED_INSTANCE_MEMBERS)) { 170 foreach (StorableAttribute attribute in memberInfo.GetCustomAttributes(typeof(StorableAttribute), false)) { 171 storableMembers.Add(new StorableMemberInfo(attribute, memberInfo)); 172 } 173 } 174 return DisentangleNameMapping(storableMembers); 175 } 176 177 private IEnumerable<DataMemberAccessor> GetStorableAccessors(object obj) { 178 foreach (var memberInfo in GetStorableMembers(obj.GetType())) 179 yield return new DataMemberAccessor( 180 memberInfo.MemberInfo, 181 memberInfo.DisentangledName, 182 memberInfo.Attribute.DefaultValue, 183 obj); 184 } 185 186 private static IEnumerable<StorableMemberInfo> DisentangleNameMapping( 187 IEnumerable<StorableMemberInfo> storableMemberInfos) { 188 var nameGrouping = new Dictionary<string, List<StorableMemberInfo>>(); 189 foreach (StorableMemberInfo storable in storableMemberInfos) { 190 if (!nameGrouping.ContainsKey(storable.MemberInfo.Name)) 191 nameGrouping[storable.MemberInfo.Name] = new List<StorableMemberInfo>(); 192 nameGrouping[storable.MemberInfo.Name].Add(storable); 193 } 194 var memberInfos = new List<StorableMemberInfo>(); 195 foreach (var storableMemberInfoGroup in nameGrouping.Values) { 196 if (storableMemberInfoGroup.Count == 1) { 197 storableMemberInfoGroup[0].SetDisentangledName(storableMemberInfoGroup[0].MemberInfo.Name); 198 memberInfos.Add(storableMemberInfoGroup[0]); 199 } else if (storableMemberInfoGroup[0].MemberInfo.MemberType == MemberTypes.Field) { 200 foreach (var storableMemberInfo in storableMemberInfoGroup) { 201 storableMemberInfo.SetDisentangledName(storableMemberInfo.FullyQualifiedMemberName); 202 memberInfos.Add(storableMemberInfo); 203 } 204 } else { 205 memberInfos.AddRange(MergePropertyAccessors(storableMemberInfoGroup)); 206 } 207 } 208 return memberInfos; 209 } 210 211 private static IEnumerable<StorableMemberInfo> MergePropertyAccessors(List<StorableMemberInfo> members) { 212 var uniqueAccessors = new Dictionary<Type, StorableMemberInfo>(); 213 foreach (var member in members) 214 uniqueAccessors[member.GetPropertyDeclaringBaseType()] = member; 215 if (uniqueAccessors.Count == 1) { 216 var storableMemberInfo = uniqueAccessors.Values.First(); 217 storableMemberInfo.SetDisentangledName(storableMemberInfo.MemberInfo.Name); 218 yield return storableMemberInfo; 219 } else { 220 foreach (var attribute in uniqueAccessors.Values) { 221 attribute.SetDisentangledName(attribute.FullyQualifiedMemberName); 222 yield return attribute; 223 } 224 } 225 } 226 227 private static bool IsEmptyOrStorableType(Type type, bool recusrive) { 228 if (IsEmptyType(type, recusrive)) return true; 229 if (!HastStorableClassAttribute(type)) return false; 230 return !recusrive || type.BaseType == null || IsEmptyOrStorableType(type.BaseType, true); 231 } 232 233 private static bool HastStorableClassAttribute(Type type) { 234 return type.GetCustomAttributes(typeof(StorableClassAttribute), false).Length > 0; 235 } 236 237 private static bool IsEmptyType(Type type, bool recursive) { 238 foreach (MemberInfo memberInfo in type.GetMembers(DECLARED_INSTANCE_MEMBERS)) { 239 if (IsModifiableMember(memberInfo)) return false; 240 } 241 return !recursive || type.BaseType == null || IsEmptyType(type.BaseType, true); 242 } 243 244 private static bool IsModifiableMember(MemberInfo memberInfo) { 245 return memberInfo.MemberType == MemberTypes.Field && IsModifiableField((FieldInfo)memberInfo) || 246 memberInfo.MemberType == MemberTypes.Property && IsModifiableProperty((PropertyInfo)memberInfo); 247 } 248 249 private static bool IsModifiableField(FieldInfo fi) { 250 return !fi.IsLiteral && !fi.IsInitOnly; 251 } 252 253 private static bool IsModifiableProperty(PropertyInfo pi) { 254 return pi.CanWrite; 255 } 127 } 256 128 257 129 private ConstructorInfo GetStorableConstructor(Type type) { … … 273 145 } 274 146 147 private IEnumerable<DataMemberAccessor> GetStorableAccessors(object obj) { 148 return GetStorableMembers(obj.GetType()) 149 .Select(mi => new DataMemberAccessor(mi.MemberInfo, mi.DisentangledName, mi.DefaultValue, obj)); 150 } 151 275 152 #endregion 153 276 154 } 155 277 156 } -
trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj
r3005 r3029 119 119 <Compile Include="Default\CompositeSerializers\NumberEnumerable2StringSerializer.cs" /> 120 120 <Compile Include="Default\CompositeSerializers\StackSerializer.cs" /> 121 <Compile Include="Default\CompositeSerializers\Storable\StorableReflection.cs" /> 122 <Compile Include="Default\CompositeSerializers\Storable\StorableMemberInfo.cs" /> 123 <Compile Include="Default\CompositeSerializers\Storable\StorableClassType.cs" /> 121 124 <Compile Include="Default\CompositeSerializers\Storable\DataMemberAccessor.cs" /> 122 125 <Compile Include="Default\CompositeSerializers\Storable\StorableClassAttribute.cs" /> -
trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs
r3017 r3029 815 815 } 816 816 817 [StorableClass(StorableClassType.AllFields)] 818 public class AllFieldsStorable { 819 public int Value1 = 1; 820 [Storable] 821 public int Value2 = 2; 822 public int Value3 { get; private set; } 823 public int Value4 { get; private set; } 824 [StorableConstructor] 825 public AllFieldsStorable(bool isDeserializing) { 826 if (!isDeserializing) { 827 Value1 = 12; 828 Value2 = 23; 829 Value3 = 34; 830 Value4 = 56; 831 } 832 } 833 } 834 835 [TestMethod] 836 public void TestStorableClassDiscoveryAllFields() { 837 AllFieldsStorable afs = new AllFieldsStorable(false); 838 XmlGenerator.Serialize(afs, tempFile); 839 AllFieldsStorable newAfs = (AllFieldsStorable)XmlParser.Deserialize(tempFile); 840 Assert.AreEqual(afs.Value1, newAfs.Value1); 841 Assert.AreEqual(afs.Value2, newAfs.Value2); 842 Assert.AreEqual(0, newAfs.Value3); 843 Assert.AreEqual(0, newAfs.Value4); 844 } 845 846 [StorableClass(StorableClassType.AllProperties)] 847 public class AllPropertiesStorable { 848 public int Value1 = 1; 849 [Storable] 850 public int Value2 = 2; 851 public int Value3 { get; private set; } 852 public int Value4 { get; private set; } 853 [StorableConstructor] 854 public AllPropertiesStorable(bool isDeserializing) { 855 if (!isDeserializing) { 856 Value1 = 12; 857 Value2 = 23; 858 Value3 = 34; 859 Value4 = 56; 860 } 861 } 862 } 863 864 [TestMethod] 865 public void TestStorableClassDiscoveryAllProperties() { 866 AllPropertiesStorable afs = new AllPropertiesStorable(false); 867 XmlGenerator.Serialize(afs, tempFile); 868 AllPropertiesStorable newAfs = (AllPropertiesStorable)XmlParser.Deserialize(tempFile); 869 Assert.AreEqual(1, newAfs.Value1); 870 Assert.AreEqual(2, newAfs.Value2); 871 Assert.AreEqual(afs.Value3, newAfs.Value3); 872 Assert.AreEqual(afs.Value4, newAfs.Value4); 873 874 } 875 876 [StorableClass(StorableClassType.AllFieldsAndAllProperties)] 877 public class AllFieldsAndAllPropertiesStorable { 878 public int Value1 = 1; 879 [Storable] 880 public int Value2 = 2; 881 public int Value3 { get; private set; } 882 public int Value4 { get; private set; } 883 [StorableConstructor] 884 public AllFieldsAndAllPropertiesStorable(bool isDeserializing) { 885 if (!isDeserializing) { 886 Value1 = 12; 887 Value2 = 23; 888 Value3 = 34; 889 Value4 = 56; 890 } 891 } 892 } 893 894 [TestMethod] 895 public void TestStorableClassDiscoveryAllFieldsAndAllProperties() { 896 AllFieldsAndAllPropertiesStorable afs = new AllFieldsAndAllPropertiesStorable(false); 897 XmlGenerator.Serialize(afs, tempFile); 898 AllFieldsAndAllPropertiesStorable newAfs = (AllFieldsAndAllPropertiesStorable)XmlParser.Deserialize(tempFile); 899 Assert.AreEqual(afs.Value1, newAfs.Value1); 900 Assert.AreEqual(afs.Value2, newAfs.Value2); 901 Assert.AreEqual(afs.Value3, newAfs.Value3); 902 Assert.AreEqual(afs.Value4, newAfs.Value4); 903 } 904 905 [StorableClass(StorableClassType.MarkedOnly)] 906 public class MarkedOnlyStorable { 907 public int Value1 = 1; 908 [Storable] 909 public int Value2 = 2; 910 public int Value3 { get; private set; } 911 public int Value4 { get; private set; } 912 [StorableConstructor] 913 public MarkedOnlyStorable(bool isDeserializing) { 914 if (!isDeserializing) { 915 Value1 = 12; 916 Value2 = 23; 917 Value3 = 34; 918 Value4 = 56; 919 } 920 } 921 } 922 923 [TestMethod] 924 public void TestStorableClassDiscoveryMarkedOnly() { 925 MarkedOnlyStorable afs = new MarkedOnlyStorable(false); 926 XmlGenerator.Serialize(afs, tempFile); 927 MarkedOnlyStorable newAfs = (MarkedOnlyStorable)XmlParser.Deserialize(tempFile); 928 Assert.AreEqual(1, newAfs.Value1); 929 Assert.AreEqual(afs.Value2, newAfs.Value2); 930 Assert.AreEqual(0, newAfs.Value3); 931 Assert.AreEqual(0, newAfs.Value4); 932 } 933 934 935 817 936 [ClassInitialize] 818 937 public static void Initialize(TestContext testContext) {
Note: See TracChangeset
for help on using the changeset viewer.