#region License Information /* HeuristicLab * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Persistence { public sealed class TypeInfo { private Func constructor; public Type Type { get; private set; } public ITransformer Transformer { get; private set; } public StorableClassAttribute StorableClassAttribute { get; private set; } public IEnumerable Fields { get; private set; } public IEnumerable Properties { get; private set; } public IEnumerable BeforeSerializationHooks { get; private set; } public IEnumerable AfterDeserializationHooks { get; private set; } public long Used { get; set; } public TypeInfo(Type type) { constructor = null; Type = type; Fields = Enumerable.Empty(); Properties = Enumerable.Empty(); BeforeSerializationHooks = Enumerable.Empty(); AfterDeserializationHooks = Enumerable.Empty(); Used = 0; Reflect(); } public TypeInfo(Type type, ITransformer transformer) : this(type) { Transformer = transformer; } private void Reflect() { var type = Type; StorableClassAttribute = StorableClassAttribute.GetStorableClassAttribute(type); if (StorableClassAttribute != null) { // traverse type hierarchy from base type to sub types Stack types = new Stack(); while (type != null) { types.Push(type); type = type.BaseType; } var fields = new List(); var properties = new List(); var beforeSerializationHooks = new List(); var afterDeserializationHooks = new List(); while (types.Count > 0) { type = types.Pop(); var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic). Where(x => StorableAttribute.IsStorable(x)); foreach (var field in fieldInfos) { var attrib = StorableAttribute.GetStorableAttribute(field); var name = string.IsNullOrEmpty(attrib.Name) ? field.Name : attrib.Name; fields.Add(new ComponentInfo(name, field, attrib, true, true)); } var propertyInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic). Where(x => x.GetIndexParameters().Length == 0). // exclude indexed properties Where(x => StorableAttribute.IsStorable(x)); foreach (var property in propertyInfos) { var attrib = StorableAttribute.GetStorableAttribute(property); var name = string.IsNullOrEmpty(attrib.Name) ? property.Name : attrib.Name; properties.Add(new ComponentInfo(name, property, attrib, property.CanRead, property.CanWrite)); } var methodInfos = type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic). Where(x => StorableHookAttribute.IsStorableHook(x)). Where(x => (x.ReturnType == typeof(void)) && (x.GetParameters().Length == 0)); foreach (var method in methodInfos) { foreach (var attrib in StorableHookAttribute.GetStorableHookAttributes(method)) { if (attrib.HookType == HookType.BeforeSerialization) beforeSerializationHooks.Add(method); if (attrib.HookType == HookType.AfterDeserialization) afterDeserializationHooks.Add(method); } } } Fields = fields; Properties = properties; BeforeSerializationHooks = beforeSerializationHooks; AfterDeserializationHooks = afterDeserializationHooks; } } public Func GetConstructor() { if (constructor != null) return constructor; // get storable constructor var ctor = Type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => StorableConstructorAttribute.IsStorableConstructor(x)) .Where(x => (x.GetParameters().Length == 1) && (x.GetParameters()[0].ParameterType == typeof(bool))) .FirstOrDefault(); if (ctor != null) { DynamicMethod dm = new DynamicMethod("", typeof(object), null, Type, true); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit(OpCodes.Ldc_I4_1); // load true ilgen.Emit(OpCodes.Newobj, ctor); ilgen.Emit(OpCodes.Ret); constructor = (Func)dm.CreateDelegate(typeof(Func)); return constructor; } // get default constructor ctor = Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (ctor != null) { DynamicMethod dm = new DynamicMethod("", typeof(object), null, Type, true); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit(OpCodes.Newobj, ctor); ilgen.Emit(OpCodes.Ret); constructor = (Func)dm.CreateDelegate(typeof(Func)); return constructor; } throw new Exception("No storable constructor or parameterless constructor found."); } } }