Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
YamlSerializer.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Reflection;
7 using SharpYaml;
8 using SharpYaml.Serialization;
9 using SiliconStudio.Core.Reflection;
11 
12 namespace SiliconStudio.Core.Yaml
13 {
14  /// <summary>
15  /// Default Yaml serializer used to serialize assets by default.
16  /// </summary>
17  public static class YamlSerializer
18  {
19  // TODO: This code is not robust in case of reloading assemblies into the same process
20  private static readonly HashSet<Assembly> RegisteredAssemblies = new HashSet<Assembly>();
21  private static readonly object Lock = new object();
22  private static Serializer globalSerializer;
23  private static Serializer globalSerializerKeepOnlySealedOverrides;
24 
25  /// <summary>
26  /// Deserializes an object from the specified stream (expecting a YAML string).
27  /// </summary>
28  /// <param name="stream">A YAML string from a stream .</param>
29  /// <returns>An instance of the YAML data.</returns>
30  public static object Deserialize(Stream stream)
31  {
32  var serializer = GetYamlSerializer(false);
33  return serializer.Deserialize(stream);
34  }
35 
36  /// <summary>
37  /// Serializes an object to specified stream in YAML format.
38  /// </summary>
39  /// <param name="stream">The stream to receive the YAML representation of the object.</param>
40  /// <param name="instance">The instance.</param>
41  /// <param name="keepOnlySealedOverrides">if set to <c>true</c> [keep only sealed overrides].</param>
42  public static void Serialize(Stream stream, object instance, bool keepOnlySealedOverrides = false)
43  {
44  var serializer = GetYamlSerializer(keepOnlySealedOverrides);
45  serializer.Serialize(stream, instance);
46  }
47 
48  public static SerializerSettings GetSerializerSettings()
49  {
50  return GetYamlSerializer(false).Settings;
51  }
52 
53  private static Serializer GetYamlSerializer(bool keepOnlySealedOverrides)
54  {
55  Serializer localSerializer;
56  // Cache serializer to improve performance
57  lock (Lock)
58  {
59  localSerializer = keepOnlySealedOverrides ? CreateSerializer(true, ref globalSerializerKeepOnlySealedOverrides) : CreateSerializer(false, ref globalSerializer);
60  }
61  return localSerializer;
62  }
63 
64  private static Serializer CreateSerializer(bool keepOnlySealedOverrides, ref Serializer localSerializer)
65  {
66  if (localSerializer == null)
67  {
68  var config = new SerializerSettings()
69  {
70  EmitAlias = false,
71  LimitPrimitiveFlowSequence = 0,
72  Attributes = new AtributeRegistryFilter(),
73  PreferredIndent = 4,
74  };
75 
76  foreach (var registeredAssembly in RegisteredAssemblies)
77  {
78  config.RegisterAssembly(registeredAssembly);
79  }
80 
81  localSerializer = new Serializer(config);
82  localSerializer.Settings.ObjectSerializerBackend = new OverrideKeyMappingTransform(TypeDescriptorFactory.Default, keepOnlySealedOverrides);
83  }
84 
85  return localSerializer;
86  }
87 
88  /// <summary>
89  /// Filters attributes to replace <see cref="DataMemberAttribute"/> by <see cref="YamlMemberAttribute"/>
90  /// </summary>
91  private class AtributeRegistryFilter : AttributeRegistry
92  {
93  public override List<Attribute> GetAttributes(System.Reflection.MemberInfo memberInfo, bool inherit = true)
94  {
95  var attributes = base.GetAttributes(memberInfo, inherit);
96  for (int i = attributes.Count - 1; i >= 0; i--)
97  {
98  var attribute = attributes[i] as DataMemberAttribute;
99  if (attribute != null)
100  {
101  attributes[i] = new YamlMemberAttribute(attribute.Name) { Order = attribute.Order };
102  }
103  else if (attributes[i] is DataMemberIgnoreAttribute)
104  {
105  attributes[i] = new YamlIgnoreAttribute();
106  }
107  else if (attributes[i] is DataContractAttribute)
108  {
109  var alias = ((DataContractAttribute)attributes[i]).Alias;
110  if (!string.IsNullOrWhiteSpace(alias))
111  {
112  attributes[i] = new YamlTagAttribute(alias);
113  }
114  }
115  else if (attributes[i] is DataStyleAttribute)
116  {
117  switch (((DataStyleAttribute)attributes[i]).Style)
118  {
119  case DataStyle.Any:
120  attributes[i] = new YamlStyleAttribute(YamlStyle.Any);
121  break;
122  case DataStyle.Compact:
123  attributes[i] = new YamlStyleAttribute(YamlStyle.Flow);
124  break;
125  case DataStyle.Normal:
126  attributes[i] = new YamlStyleAttribute(YamlStyle.Block);
127  break;
128  }
129  }
130  }
131  return attributes;
132  }
133  }
134 
135  [ModuleInitializer]
136  internal static void Initialize()
137  {
138  AssemblyRegistry.AssemblyRegistered += AssemblyRegistry_AssemblyRegistered;
139  foreach (var assembly in AssemblyRegistry.FindAll())
140  {
141  RegisteredAssemblies.Add(assembly);
142  }
143  }
144 
145  private static void AssemblyRegistry_AssemblyRegistered(object sender, AssemblyRegisteredEventArgs e)
146  {
147  lock (Lock)
148  {
149  RegisteredAssemblies.Add(e.Assembly);
150 
151  // Reset the current serializer as the set of assemblies has changed
152  globalSerializer = null;
153  globalSerializerKeepOnlySealedOverrides = null;
154  }
155  }
156  }
157 }
SharpYaml.Serialization.AttributeRegistry AttributeRegistry
A default implementation for the ITypeDescriptorFactory.
static HashSet< Assembly > FindAll()
Finds all registered assemblies.
Default Yaml serializer used to serialize assets by default.
Provides a basic infrastructure to associate an assembly with some categories and to query and regist...
An event occuring when an assembly is registered with AssemblyRegistry.
document false
static SerializerSettings GetSerializerSettings()
static object Deserialize(Stream stream)
Deserializes an object from the specified stream (expecting a YAML string).
static void Serialize(Stream stream, object instance, bool keepOnlySealedOverrides=false)
Serializes an object to specified stream in YAML format.
A default implementation for IAttributeRegistry. This implementation allows to retrieve default attri...
static readonly TypeDescriptorFactory Default
The default type descriptor factory.