1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.Xml.Serialization
 10 {
 11     delegate void* FactoryFunction();
 12 
 13     public abstract class XmlSerializableExtractor
 14     {
 15         public virtual default ~XmlSerializableExtractor();
 16         public abstract nothrow XmlSerializable ExtractXmlSerializable(void* object);
 17     }
 18 
 19     public class ConcreteXmlSerializableExtractor<T> : XmlSerializableExtractor
 20     {
 21         public override nothrow XmlSerializable ExtractXmlSerializable(void* object)
 22         {
 23             if (object != null)
 24             {
 25                 T* obj = cast<T*>(object);
 26                 XmlSerializable intf = *obj;
 27                 return intf;
 28             }
 29             else
 30             {
 31                 return XmlSerializable();
 32             }
 33         }
 34     }
 35 
 36     public XmlSerializableExtractor* MakeXmlSerializableExtractor<T>()
 37     {
 38         ConcreteXmlSerializableExtractor<T>* extractor = new ConcreteXmlSerializableExtractor<T>();
 39         return extractor;
 40     }
 41 
 42     public class XmlClassRegistry
 43     {
 44         static XmlClassRegistry() : instance(new XmlClassRegistry())
 45         {
 46         }
 47         public static XmlClassRegistry& Instance()
 48         {
 49             return *instance;
 50         }
 51         private nothrow XmlClassRegistry()
 52         {
 53         }
 54         public void Register(int classIdFactoryFunction factoryFunctionXmlSerializableExtractor* extractor)
 55         {
 56             factoryMap[classId] = factoryFunction;
 57             if (extractor != null)
 58             {
 59                 extractorMap[classId] = extractor;
 60                 extractors.Add(UniquePtr<XmlSerializableExtractor>(extractor));
 61             }
 62         }
 63         public XmlSerializable CreateXmlSerializable(int classId)
 64         {
 65             Map<intXmlSerializableExtractor*>.ConstIterator it = extractorMap.CFind(classId);
 66             if (it != extractorMap.CEnd())
 67             {
 68                 XmlSerializableExtractor* extractor = it->second;
 69                 void* object = Create(classId);
 70                 return extractor->ExtractXmlSerializable(object);
 71             }
 72             else
 73             {
 74                 throw XmlSerializationException("interface extractor for class id " + ToString(classId) + " not registered");
 75             }
 76         }
 77         public void* Create(int classId)
 78         {
 79             Map<intFactoryFunction>.ConstIterator it = factoryMap.CFind(classId);
 80             if (it != factoryMap.CEnd())
 81             {
 82                 FactoryFunction factoryFunction = it->second;
 83                 return factoryFunction();
 84             }
 85             else
 86             {
 87                 throw XmlSerializationException("class having id " + ToString(classId) + " not registered");
 88             }
 89         }
 90         private static UniquePtr<XmlClassRegistry> instance;
 91         private Map<intFactoryFunction> factoryMap;
 92         private Map<intXmlSerializableExtractor*> extractorMap;
 93         private List<UniquePtr<XmlSerializableExtractor>> extractors;
 94     }
 95 
 96     public void XmlRegister<T>(int classId)
 97     {
 98         XmlClassRegistry.Instance().Register(classIdT.CreateMakeXmlSerializableExtractor<T>());
 99     }
100 }
101