#nullable enable using IPA.Config.Stores.Converters; using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; namespace IPA.Config.Stores.Attributes { /// /// Indicates that the generated subclass of the attribute's target should implement . /// If the type this is applied to already inherits it, this is implied. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public sealed class NotifyPropertyChangesAttribute : Attribute { } /// /// Causes a field or property in an object being wrapped by to be /// ignored during serialization and deserialization. /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class IgnoreAttribute : Attribute { } /// /// Indicates that a field or property in an object being wrapped by /// that would otherwise be nullable (i.e. a reference type or a type) should never be null, and the /// member will be ignored if the deserialized value is . /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class NonNullableAttribute : Attribute { } /// /// Indicates that a given field or property in an object being wrapped by /// should be serialized and deserialized using the provided converter instead of the default mechanism. /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class UseConverterAttribute : Attribute { /// /// Gets whether or not to use the default converter for the member type instead of the specified type. /// [MemberNotNullWhen(false, nameof(ConverterType))] public bool UseDefaultConverterForType { get; } /// /// Gets the type of the converter to use. /// public Type? ConverterType { get; } /// /// Gets the target type of the converter if it is avaliable at instantiation time, otherwise /// . /// public Type? ConverterTargetType { get; } /// /// Gets whether or not this converter is a generic . /// [MemberNotNullWhen(true, nameof(ConverterTargetType))] public bool IsGenericConverter => ConverterTargetType is not null; /// /// Creates a new specifying to use the default converter type for the target member. /// public UseConverterAttribute() => UseDefaultConverterForType = true; /// /// Creates a new with a given . /// /// the type to assign to public UseConverterAttribute(Type converterType) { if (converterType is null) throw new ArgumentNullException(nameof(converterType)); UseDefaultConverterForType = false; ConverterType = converterType; if (converterType.IsValueType) throw new ArgumentException("Type is not a value converter!"); var baseT = ConverterType.BaseType; while (baseT != typeof(object) && (!baseT.IsGenericType || baseT.GetGenericTypeDefinition() != typeof(ValueConverter<>))) baseT = baseT.BaseType; if (baseT == typeof(object)) ConverterTargetType = null; else ConverterTargetType = baseT.GetGenericArguments()[0]; var implInterface = ConverterType.GetInterfaces().Contains(typeof(IValueConverter)); if (ConverterTargetType == null && !implInterface) throw new ArgumentException("Type is not a value converter!"); } } /// /// Specifies a name for the serialized field or property in an object being wrapped by /// that is different from the member name itself. /// /// /// /// When serializing the following object, we might get the JSON that follows. /// /// public class PluginConfig /// { /// public virtual bool BooleanField { get; set; } = true; /// } /// /// /// { /// "BooleanField": true /// } /// /// /// /// However, if we were to add a to that field, we would get the following. /// /// public class PluginConfig /// { /// [SerializedName("bool")] /// public virtual bool BooleanField { get; set; } = true; /// } /// /// /// { /// "bool": true /// } /// /// /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class SerializedNameAttribute : Attribute { /// /// Gets the name to replace the member name with. /// public string Name { get; private set; } /// /// Creates a new with the given . /// /// the value to assign to public SerializedNameAttribute(string name) { Name = name; } } }