3 using System.Runtime.CompilerServices;
4 using SiliconStudio.Core.Serialization.Serializers;
5 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
7 using System.CodeDom.Compiler;
8 using System.Collections.Generic;
14 namespace SiliconStudio.AssemblyProcessor
16 internal partial class ComplexClassSerializerGenerator
18 private TypeDefinition type;
19 private bool hasParentSerializer;
20 private static HashSet<string> forbiddenKeywords;
22 static ComplexClassSerializerGenerator()
24 forbiddenKeywords =
new HashSet<string>(
new[]
25 {
"obj",
"stream",
"mode",
26 "abstract",
"event",
"new",
"struct",
27 "as",
"explicit",
"null",
"switch",
28 "base",
"extern",
"object",
"this",
29 "bool",
"false",
"operator",
"throw",
30 "break",
"finally",
"out",
"true",
31 "byte",
"fixed",
"override",
"try",
32 "case",
"float",
"params",
"typeof",
33 "catch",
"for",
"private",
"uint",
34 "char",
"foreach",
"protected",
"ulong",
35 "checked",
"goto",
"public",
"unchecked",
36 "class",
"if",
"readonly",
"unsafe",
37 "const",
"implicit",
"ref",
"ushort",
38 "continue",
"in",
"return",
"using",
39 "decimal",
"int",
"sbyte",
"virtual",
40 "default",
"interface",
"sealed",
"volatile",
41 "delegate",
"internal",
"short",
"void",
42 "do",
"is",
"sizeof",
"while",
43 "double",
"lock",
"stackalloc",
44 "else",
"long",
"static",
45 "enum",
"namespace",
"string" });
48 public ComplexClassSerializerGenerator(TypeDefinition type,
bool hasParentSerializer)
51 this.hasParentSerializer = hasParentSerializer;
54 private static string TypeNameWithoutGenericEnding(TypeReference type)
56 var typeName = type.Name;
59 var genericCharIndex = typeName.LastIndexOf(
'`');
60 if (genericCharIndex != -1)
61 typeName = typeName.Substring(0, genericCharIndex);
66 public static string SerializerTypeName(TypeReference type,
bool appendGenerics,
bool appendSerializer)
68 var typeName = TypeNameWithoutGenericEnding(type);
72 typeName = TypeNameWithoutGenericEnding(type.DeclaringType) +
"_" + typeName;
75 if (!
String.IsNullOrEmpty(type.Namespace))
76 typeName = type.Namespace.Replace(
".",
String.Empty) +
"_" + typeName;
80 typeName +=
"Serializer";
84 typeName += type.GenerateGenerics();
89 public static string GetSerializerInstantiateMethodName(TypeReference serializerType,
bool appendGenerics)
91 return "Instantiate_" + SerializerTypeName(serializerType, appendGenerics,
false);
99 public static string GenerateGenericConstraints(TypeReference type)
101 if (!type.HasGenericParameters)
104 var result =
new StringBuilder();
105 foreach (var genericParameter
in type.GenericParameters)
108 var hasContraints = genericParameter.HasReferenceTypeConstraint || genericParameter.HasNotNullableValueTypeConstraint || genericParameter.Constraints.Count > 0 || genericParameter.HasDefaultConstructorConstraint;
114 bool hasFirstContraint =
false;
116 result.AppendFormat(
" where {0}: ", genericParameter.Name);
119 if (genericParameter.HasReferenceTypeConstraint)
121 result.AppendFormat(
"class");
122 hasFirstContraint =
true;
124 else if (genericParameter.HasNotNullableValueTypeConstraint)
126 result.AppendFormat(
"struct");
127 hasFirstContraint =
true;
130 foreach (var genericParameterConstraint
in genericParameter.Constraints)
133 if (genericParameterConstraint.FullName != typeof(ValueType).FullName)
135 if (hasFirstContraint)
140 result.AppendFormat(
"{0}", genericParameterConstraint.ConvertCSharp());
143 hasFirstContraint =
true;
149 if (!genericParameter.HasNotNullableValueTypeConstraint && genericParameter.HasDefaultConstructorConstraint)
151 if (hasFirstContraint)
156 result.AppendFormat(
"new()");
161 return result.ToString();
169 protected static bool HasEmptyConstructor(TypeReference type)
171 return type.Resolve().Methods.Any(x => x.IsConstructor && x.IsPublic && !x.IsStatic && x.Parameters.Count == 0);
176 foreach (var serializableItemOriginal
in GetSerializableItems(type.Resolve(), serializeFields))
178 var serializableItem = serializableItemOriginal;
181 if (serializableItem.Type.ContainsGenericParameter())
183 serializableItem.Type = ResolveGenericsVisitor.Process(type, serializableItem.Type);
186 yield
return serializableItem;
194 var fields =
new List<FieldDefinition>();
195 var properties =
new List<PropertyDefinition>();
197 var fieldEnum = type.Fields.Where(x => x.IsPublic && !x.IsStatic);
202 if (type.IsSequentialLayout || type.IsExplicitLayout)
203 fieldEnum = fieldEnum.OrderBy(x => x.Offset);
205 fieldEnum = fieldEnum.OrderBy(x => x.Name);
207 foreach (var field
in fieldEnum)
212 foreach (var property
in type.Properties.OrderBy(x => x.Name))
215 if (property.GetMethod == null || !property.GetMethod.IsPublic || property.GetMethod.IsStatic)
219 if (property.PropertyType.IsValueType && (property.SetMethod == null || !property.SetMethod.IsPublic))
223 if (property.GetMethod.IsVirtual && !property.GetMethod.IsNewSlot)
226 properties.Add(property);
229 if (type.IsClass && !type.IsValueType)
230 flags = ComplexTypeSerializerFlags.SerializePublicFields | ComplexTypeSerializerFlags.SerializePublicProperties;
231 else if (type.Fields.Any(x => x.IsPublic && !x.IsStatic))
238 foreach (var field
in fields)
240 if (field.IsInitOnly)
242 if (field.CustomAttributes.Any(x => x.AttributeType.FullName ==
"SiliconStudio.Core.DataMemberIgnoreAttribute"))
244 var attributes = field.CustomAttributes;
245 var fixedAttribute = field.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == typeof(FixedBufferAttribute).FullName);
246 yield
return new SerializableItem { MemberInfo = field,
Type = field.FieldType, Name = field.Name, Attributes = attributes, AssignBack =
true, NeedReference =
false, HasFixedAttribute = fixedAttribute != null };
252 foreach (var property
in properties)
255 if (property.GetMethod.Parameters.Count > 0)
257 if (property.CustomAttributes.Any(x => x.AttributeType.FullName ==
"SiliconStudio.Core.DataMemberIgnoreAttribute"))
259 var attributes = property.CustomAttributes;
260 bool assignBack = property.SetMethod != null && property.SetMethod.IsPublic;
261 yield
return new SerializableItem { MemberInfo = property,
Type = property.PropertyType, Name = property.Name, Attributes = attributes, AssignBack = assignBack, NeedReference = !type.IsClass || type.IsValueType };
266 protected static string CreateMemberVariableName(IMemberDefinition memberInfo)
268 var memberVariableName = Char.ToLowerInvariant(memberInfo.Name[0]) + memberInfo.Name.Substring(1);
269 if (forbiddenKeywords.Contains(memberVariableName))
270 memberVariableName +=
"_";
271 return memberVariableName;
276 var result =
new HashSet<TypeReference>();
277 var objectTypes =
new HashSet<string>();
278 foreach (var memberType
in memberTypes)
280 EnumerateSerializerTypes(memberType, objectTypes, result);
285 protected void EnumerateSerializerTypes(TypeReference objectType, HashSet<string> objectTypes, HashSet<TypeReference> serializerTypes)
287 if (objectType.IsGenericParameter)
291 if (!objectTypes.Add(objectType.FullName))
321 public struct SerializableItem
323 public bool HasFixedAttribute;
325 public IMemberDefinition MemberInfo;
326 public TypeReference
Type;
327 public bool NeedReference;
328 public bool AssignBack;
329 public IList<CustomAttribute> Attributes;
Mono.Cecil.TypeAttributes TypeAttributes
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
ComplexTypeSerializerFlags