static void ApplyConstructorDefaults(TypeConfig typeConfig) { if (typeConfig.TypeConstruction != null) { return; } if (typeConfig.TypeConstruction == null) { if (CerasSerializer.IsFormatterConstructed(typeConfig.Type) || (typeConfig.Type.IsStatic())) { typeConfig.TypeConstruction = TypeConstruction.Null(); return; } } var type = typeConfig.Type; MethodBase ctor; // Try hint by attribute IEnumerable <MethodBase> methods = type.GetMethods(BindingFlagsStatic).Cast <MethodBase>().Concat(type.GetConstructors(BindingFlagsCtor)); var cerasCtors = methods.Where(m => m.GetCustomAttribute <CerasConstructorAttribute>() != null).ToArray(); if (cerasCtors.Length > 1) { // Multiple matches throw new InvalidConfigException($"There are multiple constructors on your type '{typeConfig.Type.Name}' that have the '[CerasConstructor]' attribute, so its unclear which one to use. Only one constructor in this type can have the attribute."); } else if (cerasCtors.Length == 1) { // Single match ctor = cerasCtors[0]; } else { // No match, try default ctor ctor = type.GetConstructors(BindingFlagsCtor).FirstOrDefault(c => c.GetParameters().Length == 0); } // Apply this ctor or factory if (ctor != null) { if (ctor is ConstructorInfo constructorInfo) { typeConfig.TypeConstruction = TypeConstruction.ByConstructor(constructorInfo); } else if (ctor is MethodInfo methodInfo) { typeConfig.TypeConstruction = TypeConstruction.ByStaticMethod(methodInfo); } } if (type.IsValueType && typeConfig.TypeConstruction == null) { typeConfig.TypeConstruction = ConstructNull.Instance; } }
static void ForceSerialization(TypeConfig typeConfig) { typeConfig.TypeConstruction = TypeConstruction.ByUninitialized(); typeConfig.ReadonlyFieldOverride = ReadonlyFieldHandling.ForcedOverwrite; typeConfig.TargetMembers = TargetMember.PrivateFields; typeConfig.CustomResolver = ForceDynamicResolver; }
// Built-in support for some specific types internal static void ApplySpecializedDefaults(TypeConfig typeConfig) { var type = typeConfig.Type; // All structs if (!type.IsPrimitive && type.IsValueType) { if (typeConfig.TypeConstruction == null) { typeConfig.TypeConstruction = ConstructNull.Instance; } typeConfig.TargetMembers = TargetMember.AllFields; typeConfig.ReadonlyFieldOverride = ReadonlyFieldHandling.ForcedOverwrite; return; } // Version if (type == typeof(Version)) { ForceSerialization(typeConfig); return; } // Expression & TrueReadOnlyCollection if (type.Assembly == typeof(Expression).Assembly) { if (!type.IsAbstract && type.IsSubclassOf(typeof(Expression))) { ForceSerialization(typeConfig); return; } if (type.FullName.StartsWith("System.Runtime.CompilerServices.TrueReadOnlyCollection")) { ForceSerialization(typeConfig); return; } } // ReadOnlyCollection if (type.Assembly == typeof(ReadOnlyCollection <>).Assembly) { if (type.FullName.StartsWith("System.Collections.ObjectModel.ReadOnlyCollection")) { ForceSerialization(typeConfig); return; } } }
// Apply default settings to the newly created TypeConfig based on the attributes on the Type internal static void ApplyTypeAttributes(TypeConfig typeConfig) { var type = typeConfig.Type; // // Constructor ApplyConstructorDefaults(typeConfig); // // Set default values from attributes var memberConfigAttrib = type.GetCustomAttribute <MemberConfigAttribute>(); if (memberConfigAttrib != null) { typeConfig.ReadonlyFieldOverride = memberConfigAttrib.ReadonlyFieldHandling; typeConfig.TargetMembers = memberConfigAttrib.TargetMembers; } }