LispSerializer.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // $Id$
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Reflection;
  6. using System.IO;
  7. using Lisp;
  8. namespace LispReader
  9. {
  10. /// <summary>This class allows serialization of .net Classes to/from lisp constructs.</summary>
  11. /// <remarks>
  12. /// <para>You just have to annotate the class to specify a mapping from fields/lists to
  13. /// lisp structures.</para>
  14. /// <para>The design is similar to <see cref="System.Xml.Serialization.XmlSerializer"/></para>
  15. /// </remarks>
  16. public class LispSerializer {
  17. private Type RootType;
  18. private static Dictionary<Type, ILispSerializer> typeSerializers
  19. = new Dictionary<Type, ILispSerializer>();
  20. static LispSerializer()
  21. {
  22. SetupSerializers(typeof(LispSerializer).Assembly);
  23. }
  24. public LispSerializer(Type RootType)
  25. {
  26. this.RootType = RootType;
  27. }
  28. public void Write(string FileName, object Object)
  29. {
  30. TextWriter Writer = new StreamWriter(FileName);
  31. try {
  32. Write(Writer, FileName, Object);
  33. } finally {
  34. Writer.Close();
  35. }
  36. }
  37. public void Write(TextWriter TextWriter, string Dest, object Object)
  38. {
  39. LispRootAttribute rootAttrib = (LispRootAttribute)
  40. Attribute.GetCustomAttribute(RootType, typeof(LispRootAttribute));
  41. if(rootAttrib == null)
  42. throw new LispException("Type needs to have LispRoot attribute");
  43. Writer Writer = new Writer(TextWriter);
  44. Write(Writer, rootAttrib.Name, Object);
  45. }
  46. public void Write(Writer Writer, string name, object Object)
  47. {
  48. WriteType(Writer, RootType, name, Object);
  49. }
  50. public object Read(string FileName)
  51. {
  52. TextReader Reader = new StreamReader(FileName);
  53. try {
  54. return Read(Reader, FileName);
  55. } finally {
  56. Reader.Close();
  57. }
  58. }
  59. public object Read(TextReader Reader, string Source)
  60. {
  61. LispRootAttribute RootAttrib = (LispRootAttribute)
  62. Attribute.GetCustomAttribute(RootType, typeof(LispRootAttribute));
  63. if(RootAttrib == null)
  64. throw new LispException("Type needs to have LispRoot attribute");
  65. Lexer Lexer = new Lexer(Reader);
  66. Parser Parser = new Parser(Lexer);
  67. List Root = Parser.Parse();
  68. Properties RootP = new Properties(Root);
  69. List List = null;
  70. if(!RootP.Get(RootAttrib.Name, ref List))
  71. throw new LispException("'" + Source + "' is not a " + RootAttrib.Name + " file");
  72. return ReadType(RootType, List);
  73. }
  74. public object Read(List List)
  75. {
  76. return ReadType(RootType, List);
  77. }
  78. private static object ReadType(Type type, List list)
  79. {
  80. ILispSerializer serializer = GetSerializer(type);
  81. if(serializer == null)
  82. serializer = CreateRootSerializer(type);
  83. return serializer.Read(list);
  84. }
  85. private static void WriteType(Writer writer, Type type, string name, object Object)
  86. {
  87. ILispSerializer serializer = GetSerializer(type);
  88. if(serializer == null)
  89. serializer = CreateRootSerializer(type);
  90. serializer.Write(writer, name, Object);
  91. }
  92. private static object CreateObject(Type Type)
  93. {
  94. // create object
  95. ConstructorInfo Constructor = Type.GetConstructor(Type.EmptyTypes);
  96. if(Constructor == null)
  97. throw new LispException("Type '" + Type + "' has no public constructor without arguments");
  98. object Result = Constructor.Invoke(new object[] {});
  99. return Result;
  100. }
  101. public static ILispSerializer GetSerializer(Type type)
  102. {
  103. ILispSerializer result;
  104. typeSerializers.TryGetValue(type, out result);
  105. return result;
  106. }
  107. public static void SetupSerializers(Assembly assembly)
  108. {
  109. foreach(Type type in assembly.GetTypes()) {
  110. ScanType(type);
  111. }
  112. }
  113. public static void ScanType(Type type)
  114. {
  115. foreach(Type nestedType in type.GetNestedTypes())
  116. ScanType(nestedType);
  117. LispCustomSerializerAttribute customSerializer =
  118. (LispCustomSerializerAttribute)
  119. Attribute.GetCustomAttribute(type, typeof(LispCustomSerializerAttribute));
  120. if(customSerializer != null) {
  121. object instance = CreateObject(type);
  122. typeSerializers.Add(customSerializer.Type, (ILispSerializer) instance);
  123. return;
  124. }
  125. LispRootAttribute rootAttrib = (LispRootAttribute)
  126. Attribute.GetCustomAttribute(type, typeof(LispRootAttribute));
  127. if(rootAttrib != null) {
  128. LispRootSerializer serializer = new LispRootSerializer(type);
  129. typeSerializers.Add(type, serializer);
  130. return;
  131. }
  132. }
  133. internal static ILispSerializer CreateRootSerializer(Type type)
  134. {
  135. LispRootSerializer serializer = new LispRootSerializer(type);
  136. typeSerializers.Add(type, serializer);
  137. return serializer;
  138. }
  139. }
  140. }