protected void OnSetupInstance() { Type type = GetType(); Type serializableType = typeof(Serializable); // Only do this for user types. if (type.Assembly == serializableType.Assembly || !type.IsSubclassOf(serializableType)) { return; } AttributeMap allAttributes = Context.AllAttributes; // And only once per type. if (allAttributes.ContainsKey(GetTypeHash())) { return; } // Register field attributes of this class foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.DeclaringType?.Assembly == serializableType.Assembly) { continue; } if (field.IsNotSerialized) { continue; } var attribute = Attribute.GetCustomAttribute(field, typeof(SerializeFieldAttribute)) as SerializeFieldAttribute; if (field.IsPrivate && attribute == null) { continue; } Type fieldType = field.FieldType; if (fieldType.IsEnum) { fieldType = Enum.GetUnderlyingType(fieldType); } VariantType variantType = Variant.GetVariantType(fieldType); // TODO: Support VariantType.VarPtr if (variantType == VariantType.VarNone || variantType == VariantType.VarPtr || variantType == VariantType.VarVoidPtr) { // Incompatible type. Log.Warning($"Trying to register attribute {field.DeclaringType?.FullName}.{field.Name} which has incompatible type {field.FieldType.Name}."); continue; } StringList enumNames = _emptyStringList; if (field.FieldType.IsEnum) { enumNames = new StringList(); foreach (string name in field.FieldType.GetEnumNames()) { enumNames.Add(name); } } var accessor = new VariantFieldAccessor(field, variantType); var defaultValue = new Variant(); try { accessor.Get(this, defaultValue); } catch (ArgumentNullException) { defaultValue = new Variant(variantType); } string attributeName = attribute?.Name ?? field.Name; var info = new AttributeInfo(accessor.VariantType, attributeName, accessor, enumNames, defaultValue, attribute?.Mode ?? AttributeMode.AmDefault); Context.RegisterAttribute(GetTypeHash(), info); } // Register property attributes of this class foreach (PropertyInfo property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (property.DeclaringType?.Assembly == serializableType.Assembly) { continue; } // Private (even if partially) properties are not serialized by default. var attribute = Attribute.GetCustomAttribute(property, typeof(SerializeFieldAttribute)) as SerializeFieldAttribute; if ((property.GetMethod.IsPrivate || property.SetMethod.IsPrivate) && attribute == null) { continue; } if (!property.CanRead || !property.CanWrite) { Log.Warning($"Trying to register attribute {property.DeclaringType?.FullName}.{property.Name} which is not readable and writable."); continue; } Type propertyType = property.PropertyType; if (propertyType.IsEnum) { propertyType = Enum.GetUnderlyingType(propertyType); } VariantType variantType = Variant.GetVariantType(propertyType); // TODO: Support VariantType.VarPtr if (variantType == VariantType.VarNone || variantType == VariantType.VarPtr || variantType == VariantType.VarVoidPtr) { // Incompatible type. Log.Warning($"Trying to register attribute {property.DeclaringType?.FullName}.{property.Name} which has incompatible type {property.PropertyType.Name}."); continue; } StringList enumNames = _emptyStringList; if (property.PropertyType.IsEnum) { enumNames = new StringList(); foreach (string name in property.PropertyType.GetEnumNames()) { enumNames.Add(name); } } var accessor = new VariantPropertyAccessor(property, variantType); var defaultValue = new Variant(); try { accessor.Get(this, defaultValue); } catch (ArgumentNullException) { defaultValue = new Variant(variantType); } string attributeName = attribute?.Name ?? property.Name; var info = new AttributeInfo(accessor.VariantType, attributeName, accessor, enumNames, defaultValue, attribute?.Mode ?? AttributeMode.AmDefault); Context.RegisterAttribute(GetTypeHash(), info); } }
protected void OnSetupInstance() { var type = GetType(); var serializableType = typeof(Serializable); // Only do this for user types. if (type.Assembly == serializableType.Assembly || !type.IsSubclassOf(serializableType)) { return; } var context = Context; var allAttributes = context.AllAttributes; // And only once per type. if (allAttributes.ContainsKey(GetTypeHash())) { return; } // Register attributes of this class foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.DeclaringType?.Assembly == serializableType.Assembly) { continue; } if (field.IsNotSerialized) { continue; } var attribute = Attribute.GetCustomAttribute(field, typeof(SerializeFieldAttribute)) as SerializeFieldAttribute; if (field.IsPrivate && attribute == null) { continue; } var fieldType = field.FieldType; if (field.FieldType.IsEnum) { fieldType = Enum.GetUnderlyingType(fieldType); } var variantType = Variant.GetVariantType(fieldType); if (variantType == VariantType.VarNone) { // Incompatible type. continue; } // TODO: This needs more work. Serializable should automatically serialize instances of Serializable. if (variantType == VariantType.VarPtr) { continue; } // No way to serialize that in any meaningful way. if (variantType == VariantType.VarVoidPtr) { continue; } var enumNames = _emptyStringList; if (field.FieldType.IsEnum) { enumNames = new StringList(); foreach (var name in field.FieldType.GetEnumNames()) { enumNames.Add(name); } } var accessor = new VariantFieldAccessor(field, variantType); var defaultValue = new Variant(); accessor.Get(this, defaultValue); var attributeName = attribute?.Name ?? field.Name; var info = new AttributeInfo(accessor.VariantType, attributeName, accessor, enumNames, defaultValue, attribute?.Mode ?? AttributeMode.AmDefault); context.RegisterAttribute(GetTypeHash(), info); } }