using System; using System.Collections.Generic; using System.Linq; using HeuristicLab.Persistence.Interfaces; using HeuristicLab.Persistence.Core; using System.Reflection; using HeuristicLab.Persistence.Auxiliary; namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable { /// /// Intended for serialization of all custom classes. Classes should have the /// [StorableClass] attribute set and a serialization mode set. /// Optionally selected fields and properties can be marked with the /// [Storable] attribute. /// [StorableClass] public class StorableSerializer : ICompositeSerializer { public int Priority { get { return 200; } } public bool CanSerialize(Type type) { if (!ReflectionTools.HasDefaultConstructor(type) && StorableConstructorAttribute.GetStorableConstructor(type) == null) return false; return StorableClassAttribute.IsStorableType(type, true); } public string JustifyRejection(Type type) { if (!ReflectionTools.HasDefaultConstructor(type) && StorableConstructorAttribute.GetStorableConstructor(type) == null) return "no default constructor and no storable constructor"; return "class or one of its base classes is not empty and has no [StorableClass] attribute"; } public IEnumerable CreateMetaInfo(object o) { StorableHookAttribute.InvokeHook(HookType.BeforeSerialization, o); return new Tag[] { }; } public IEnumerable Decompose(object obj) { foreach (var accessor in StorableAttribute.GetStorableAccessors(obj)) { yield return new Tag(accessor.Name, accessor.Get()); } } private static readonly object[] defaultArgs = new object[] { true }; public object CreateInstance(Type type, IEnumerable metaInfo) { try { ConstructorInfo constructor = StorableConstructorAttribute.GetStorableConstructor(type); return constructor != null ? constructor.Invoke(defaultArgs) : Activator.CreateInstance(type, true); } catch (TargetInvocationException x) { throw new PersistenceException( "Could not instantiate storable object: Encountered exception during constructor call", x.InnerException); } } public void Populate(object instance, IEnumerable objects, Type type) { var memberDict = new Dictionary(); IEnumerator iter = objects.GetEnumerator(); while (iter.MoveNext()) { memberDict.Add(iter.Current.Name, iter.Current); } foreach (var accessor in StorableAttribute.GetStorableAccessors(instance)) { if (memberDict.ContainsKey(accessor.Name)) { accessor.Set(memberDict[accessor.Name].Value); } else if (accessor.DefaultValue != null) { accessor.Set(accessor.DefaultValue); } } StorableHookAttribute.InvokeHook(HookType.AfterDeserialization, instance); } } }