You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
5.8 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. using IPA.Config.Stores.Converters;
  2. using System;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. namespace IPA.Config.Stores.Attributes
  6. {
  7. /// <summary>
  8. /// Indicates that the generated subclass of the attribute's target should implement <see cref="INotifyPropertyChanged"/>.
  9. /// If the type this is applied to already inherits it, this is implied.
  10. /// </summary>
  11. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
  12. public sealed class NotifyPropertyChangesAttribute : Attribute { }
  13. /// <summary>
  14. /// Causes a field or property in an object being wrapped by <see cref="GeneratedStore.Generated{T}(Config, bool)"/> to be
  15. /// ignored during serialization and deserialization.
  16. /// </summary>
  17. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  18. public sealed class IgnoreAttribute : Attribute { }
  19. /// <summary>
  20. /// Indicates that a field or property in an object being wrapped by <see cref="GeneratedStore.Generated{T}(Config, bool)"/>
  21. /// that would otherwise be nullable (i.e. a reference type or a <see cref="Nullable{T}"/> type) should never be null, and the
  22. /// member will be ignored if the deserialized value is <see langword="null"/>.
  23. /// </summary>
  24. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  25. public sealed class NonNullableAttribute : Attribute { }
  26. /// <summary>
  27. /// Indicates that a given field or property in an object being wrapped by <see cref="GeneratedStore.Generated{T}(Config, bool)"/>
  28. /// should be serialized and deserialized using the provided converter instead of the default mechanism.
  29. /// </summary>
  30. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  31. public sealed class UseConverterAttribute : Attribute
  32. {
  33. /// <summary>
  34. /// Gets whether or not to use the default converter for the member type instead of the specified type.
  35. /// </summary>
  36. public bool UseDefaultConverterForType { get; }
  37. /// <summary>
  38. /// Gets the type of the converter to use.
  39. /// </summary>
  40. public Type ConverterType { get; }
  41. /// <summary>
  42. /// Gets the target type of the converter if it is avaliable at instantiation time, otherwise
  43. /// <see langword="null"/>.
  44. /// </summary>
  45. public Type ConverterTargetType { get; }
  46. /// <summary>
  47. /// Gets whether or not this converter is a generic <see cref="ValueConverter{T}"/>.
  48. /// </summary>
  49. public bool IsGenericConverter => ConverterTargetType != null;
  50. /// <summary>
  51. /// Creates a new <see cref="UseConverterAttribute"/> specifying to use the default converter type for the target member.
  52. /// </summary>
  53. public UseConverterAttribute()
  54. => UseDefaultConverterForType = true;
  55. /// <summary>
  56. /// Creates a new <see cref="UseConverterAttribute"/> with a given <see cref="ConverterType"/>.
  57. /// </summary>
  58. /// <param name="converterType">the type to assign to <see cref="ConverterType"/></param>
  59. public UseConverterAttribute(Type converterType)
  60. {
  61. UseDefaultConverterForType = false;
  62. ConverterType = converterType;
  63. var baseT = ConverterType.BaseType;
  64. while (baseT != null && baseT != typeof(object) &&
  65. (!baseT.IsGenericType || baseT.GetGenericTypeDefinition() != typeof(ValueConverter<>)))
  66. baseT = baseT.BaseType;
  67. if (baseT == typeof(object)) ConverterTargetType = null;
  68. else ConverterTargetType = baseT.GetGenericArguments()[0];
  69. var implInterface = ConverterType.GetInterfaces().Contains(typeof(IValueConverter));
  70. if (ConverterTargetType == null && !implInterface) throw new ArgumentException("Type is not a value converter!");
  71. }
  72. }
  73. /// <summary>
  74. /// Specifies a name for the serialized field or property in an object being wrapped by
  75. /// <see cref="GeneratedStore.Generated{T}(Config, bool)"/> that is different from the member name itself.
  76. /// </summary>
  77. /// <example>
  78. /// <para>
  79. /// When serializing the following object, we might get the JSON that follows.
  80. /// <code>
  81. /// public class PluginConfig
  82. /// {
  83. /// public virtual bool BooleanField { get; set; } = true;
  84. /// }
  85. /// </code>
  86. /// <code>
  87. /// {
  88. /// "BooleanField": true
  89. /// }
  90. /// </code>
  91. /// </para>
  92. /// <para>
  93. /// However, if we were to add a <see cref="SerializedNameAttribute"/> to that field, we would get the following.
  94. /// <code>
  95. /// public class PluginConfig
  96. /// {
  97. /// [SerializedName("bool")]
  98. /// public virtual bool BooleanField { get; set; } = true;
  99. /// }
  100. /// </code>
  101. /// <code>
  102. /// {
  103. /// "bool": true
  104. /// }
  105. /// </code>
  106. /// </para>
  107. /// </example>
  108. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  109. public sealed class SerializedNameAttribute : Attribute
  110. {
  111. /// <summary>
  112. /// Gets the name to replace the member name with.
  113. /// </summary>
  114. public string Name { get; private set; }
  115. /// <summary>
  116. /// Creates a new <see cref="SerializedNameAttribute"/> with the given <see cref="Name"/>.
  117. /// </summary>
  118. /// <param name="name">the value to assign to <see cref="Name"/></param>
  119. public SerializedNameAttribute(string name)
  120. {
  121. Name = name;
  122. }
  123. }
  124. }