123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // $Id$
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Reflection;
- using Lisp;
- namespace LispReader
- {
- /// <summary>Serializes and Deserializes an object based on reflection.</summary>
- /// <remarks>If someone is looking for a challenge: Speed could be improved heavily
- /// by creating CIL at runtime...</remarks>
- public class LispRootSerializer : ILispSerializer
- {
- private Type type;
- public LispRootSerializer(Type type)
- {
- this.type = type;
- }
- private void CheckRequired(LispChildAttribute ChildAttrib)
- {
- if(!ChildAttrib.Optional)
- LogManager.Log(LogLevel.Debug, "Required field '" + type.Name + "." + ChildAttrib.Name + "' was not declared in loded file.");
- }
- public object Read(List list)
- {
- object result = CreateObject(type);
- Properties props = new Properties(list);
- // iterate over all fields and properties
- foreach(FieldOrProperty field in FieldOrProperty.GetFieldsAndProperties(type)) {
- LispChildAttribute ChildAttrib = (LispChildAttribute)
- field.GetCustomAttribute(typeof(LispChildAttribute));
- if(ChildAttrib != null) {
- string Name = ChildAttrib.Name;
- if(field.Type == typeof(int)) {
- int val = 0;
- if(!props.Get(Name, ref val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if(field.Type == typeof(string)) {
- string val = null;
- if(!props.Get(Name, ref val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if(field.Type == typeof(float)) {
- float val = 0;
- if(!props.Get(Name, ref val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if (field.Type.IsEnum) {
- Enum val = null;
- if (!props.Get(Name, ref val, field.Type)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if(field.Type == typeof(bool)) {
- bool val = false;
- if(!props.Get(Name, ref val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if(field.Type == typeof(List<int>)) {
- List<int> val = new List<int>();
- if(!props.GetIntList(Name, val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else if(field.Type == typeof(List<string>)) {
- List<string> val = new List<string>();
- if(!props.GetStringList(Name, val)) {
- CheckRequired(ChildAttrib);
- } else {
- field.SetValue(result, val);
- }
- } else {
- ILispSerializer serializer = LispSerializer.GetSerializer(field.Type);
- if(serializer == null)
- throw new LispException("Type " + field.Type + " not supported for serialization");
- List val = null;
- if(!props.Get(Name, ref val)) {
- CheckRequired(ChildAttrib);
- } else {
- object oval = serializer.Read(val);
- field.SetValue(result, oval);
- }
- }
- }
- foreach(LispChildsAttribute childsAttrib in
- field.GetCustomAttributes(typeof(LispChildsAttribute))) {
- object objectList = field.GetValue(result);
- Type ListType = field.Type;
- MethodInfo AddMethod = ListType.GetMethod(
- "Add", new Type[] { childsAttrib.ListType }, null);
- if(AddMethod == null)
- throw new LispException("No Add method found for field " + field.Name);
- ILispSerializer serializer = LispSerializer.GetSerializer(childsAttrib.Type);
- if(serializer == null)
- serializer = LispSerializer.CreateRootSerializer(childsAttrib.Type);
- foreach(List childList in props.GetList(childsAttrib.Name)) {
- object child = serializer.Read(childList);
- AddMethod.Invoke(objectList, new object[] { child } );
- }
- }
- }
- if(result is ICustomLispSerializer) {
- ICustomLispSerializer custom = (ICustomLispSerializer) result;
- custom.CustomLispRead(props);
- custom.FinishRead();
- }
- return result;
- }
- public void Write(Writer writer, string name, object Object)
- {
- writer.StartList(name);
- foreach(FieldOrProperty field in FieldOrProperty.GetFieldsAndProperties(type)) {
- LispChildAttribute ChildAttrib = (LispChildAttribute)
- field.GetCustomAttribute(typeof(LispChildAttribute));
- if(ChildAttrib != null && !ChildAttrib.Transient) {
- object Value = field.GetValue(Object);
- if(Value != null) {
- if(ChildAttrib.Translatable) {
- if(!ChildAttrib.Optional || !Value.Equals(ChildAttrib.Default))
- writer.WriteTranslatable(ChildAttrib.Name, Value.ToString());
- } else {
- Type childType = field.Type;
- ILispSerializer serializer = LispSerializer.GetSerializer(childType);
- if(serializer != null) {
- serializer.Write(writer, ChildAttrib.Name, Value);
- } else {
- if(ChildAttrib.Optional && childType.IsEnum) {
- // If it is an enum we need to convert ChildAttrib.Default
- // to an enum as ChildAttrib.Default is an Int32 by some (unknown) reason.
- Enum Defval = (Enum)Enum.ToObject(childType, ChildAttrib.Default);
- if (!Value.Equals(Defval))
- writer.Write(ChildAttrib.Name, Value);
- } else if(!ChildAttrib.Optional || !Value.Equals(ChildAttrib.Default)) {
- writer.Write(ChildAttrib.Name, Value);
- }
- }
- }
- } else {
- LogManager.Log(LogLevel.Debug, "Field '" + field.Name + "' is null");
- }
- }
- foreach(LispChildsAttribute childsAttrib in
- field.GetCustomAttributes(typeof(LispChildsAttribute))) {
- if(childsAttrib != null) {
- object list = field.GetValue(Object);
- if(! (list is IEnumerable))
- throw new LispException("Field '" + field.Name + "' is not IEnumerable");
- ILispSerializer serializer = LispSerializer.GetSerializer(childsAttrib.Type);
- if(serializer == null)
- serializer = LispSerializer.CreateRootSerializer(childsAttrib.Type);
- IEnumerable enumerable = (IEnumerable) list;
- foreach(object childObject in enumerable) {
- if(childsAttrib.Type.IsAssignableFrom(childObject.GetType())) {
- serializer.Write(writer, childsAttrib.Name, childObject);
- }
- }
- }
- }
- }
- if(Object is ICustomLispSerializer) {
- ICustomLispSerializer custom = (ICustomLispSerializer) Object;
- custom.CustomLispWrite(writer);
- }
- writer.EndList(name);
- }
- private static object CreateObject(Type Type)
- {
- // create object
- ConstructorInfo Constructor = Type.GetConstructor(Type.EmptyTypes);
- if(Constructor == null)
- throw new LispException("Type '" + Type + "' has no public constructor without arguments");
- object Result = Constructor.Invoke(new object[] {});
- return Result;
- }
- }
- }
|