1+ /*==============================================================================================================================
2+ | Author Ignia, LLC
3+ | Client Ignia, LLC
4+ | Project Topics Library
5+ \=============================================================================================================================*/
6+ using System . Collections ;
7+ using System . Reflection ;
8+ using OnTopic . Attributes ;
9+
10+ namespace OnTopic . Internal . Reflection {
11+
12+ /*============================================================================================================================
13+ | CLASS: ITEM METADATA
14+ \---------------------------------------------------------------------------------------------------------------------------*/
15+ /// <summary>
16+ /// Provides metadata associated with a given parameter, method, or property.
17+ /// </summary>
18+ internal abstract class ItemMetadata {
19+
20+ /*==========================================================================================================================
21+ | PRIVATE VARIABLES
22+ \-------------------------------------------------------------------------------------------------------------------------*/
23+ private readonly static List < Type > _listTypes = new ( ) ;
24+ private readonly ICustomAttributeProvider _attributeProvider ;
25+ private readonly Type _type = default ! ;
26+ private List < Attribute > _customAttributes = default ! ;
27+
28+ /*==========================================================================================================================
29+ | CONSTRUCTOR
30+ \-------------------------------------------------------------------------------------------------------------------------*/
31+ /// <summary>
32+ /// Establishes a new instance of a <see cref="ItemMetadata"/> with required dependencies.
33+ /// </summary>
34+ static ItemMetadata ( ) {
35+ _listTypes . Add ( typeof ( IEnumerable < > ) ) ;
36+ _listTypes . Add ( typeof ( ICollection < > ) ) ;
37+ _listTypes . Add ( typeof ( IList < > ) ) ;
38+ }
39+
40+ /*==========================================================================================================================
41+ | CONSTRUCTOR
42+ \-------------------------------------------------------------------------------------------------------------------------*/
43+ /// <summary>
44+ /// Initializes a new instance of the <see cref="ItemMetadata"/> class associated with a <see cref="MemberInfo"/> or <see
45+ /// cref="ParameterInfo"/> instance.
46+ /// </summary>
47+ /// <param name="name">The <see cref="Name"/> of the <see cref="MemberInfo"/> or <see cref="ParameterInfo"/>.</param>
48+ /// <param name="attributeProvider">
49+ /// The <see cref="MemberInfo"/> or <see cref="ParameterInfo"/> associated with the <see cref="ItemMetadata"/>.
50+ /// </param>
51+ internal ItemMetadata ( string name , ICustomAttributeProvider attributeProvider ) {
52+
53+ /*------------------------------------------------------------------------------------------------------------------------
54+ | Set Fields
55+ \-----------------------------------------------------------------------------------------------------------------------*/
56+ _attributeProvider = attributeProvider ;
57+
58+ /*------------------------------------------------------------------------------------------------------------------------
59+ | Set Properties
60+ \-----------------------------------------------------------------------------------------------------------------------*/
61+ Name = name ;
62+
63+ }
64+
65+ /*==========================================================================================================================
66+ | NAME
67+ \-------------------------------------------------------------------------------------------------------------------------*/
68+ /// <inheritdoc cref="MemberInfo.Name"/>
69+ internal string Name { get ; }
70+
71+ /*==========================================================================================================================
72+ | TYPE
73+ \-------------------------------------------------------------------------------------------------------------------------*/
74+ /// <summary>
75+ /// Gets the <see cref="Type"/> associated with this member. For properties and get methods, this is the return type. For
76+ /// set methods, this is the type of the parameter.
77+ /// </summary>
78+ /// <remarks>
79+ /// Ideally, the <see cref="Type"/> would be provided as part of the <see cref="ItemMetadata"/> constructor.
80+ /// Unfortunately, however, the logic for setting this type varies based on whether it is a parameter, a methor, or a
81+ /// property. As such, it makes more sense for this logic to be implemented in derived classes. To facilitate this, the
82+ /// <see cref="Type"/> property is provided with an initter, which will automatically set <see cref="IsNullable"/>, <see
83+ /// cref="IsList"/>, and <see cref="IsConvertible"/> when it is set. If this is not done properly, dependency classes will
84+ /// not work properly, and will likely fail. Since there are only two expected derived classes—<see cref="MemberAccessor"
85+ /// /> and <see cref="ParameterMetadata"/>—this shouldn't be a problem. To help avoid this scenario, a <see cref="
86+ /// ArgumentNullException"/> is thrown with instructions in the unexpected case that <see cref="Type"/> is not set.
87+ /// </remarks>
88+ public Type Type {
89+ get {
90+ return _type ?? throw new ArgumentNullException (
91+ nameof ( Type ) ,
92+ $ "This { nameof ( Type ) } property must be initialized by classes derived by { nameof ( ItemMetadata ) } "
93+ ) ;
94+ }
95+ init {
96+ _type = value ;
97+ IsNullable = ! Type . IsValueType || Nullable . GetUnderlyingType ( Type ) != null ;
98+ IsList = isList ( ) ;
99+ IsConvertible = AttributeValueConverter . IsConvertible ( Type ) ;
100+ bool isList ( )
101+ => typeof ( IList ) . IsAssignableFrom ( Type ) || Type . IsGenericType && _listTypes . Contains ( Type . GetGenericTypeDefinition ( ) ) ;
102+ }
103+ }
104+
105+ /*==========================================================================================================================
106+ | IS NULLABLE?
107+ \-------------------------------------------------------------------------------------------------------------------------*/
108+ /// <summary>
109+ /// Determine if the member accepts null values.
110+ /// </summary>
111+ /// <remarks>
112+ /// If the <see cref="Type"/> is a reference type, then it will always accept null values; this doesn't detect C# 9.0
113+ /// nullable reference types.
114+ /// </remarks>
115+ internal bool IsNullable { get ; init ; }
116+
117+ /*==========================================================================================================================
118+ | IS LIST?
119+ \-------------------------------------------------------------------------------------------------------------------------*/
120+ /// <summary>
121+ /// Determine if the member is a <see cref="IList"/>, <see cref="IList{T}"/>, <see cref="IEnumerable{T}"/>, or <see cref="
122+ /// ICollection{T}"/>.
123+ /// </summary>
124+ internal bool IsList { get ; init ; }
125+
126+ /*==========================================================================================================================
127+ | IS CONVERTIBLE?
128+ \-------------------------------------------------------------------------------------------------------------------------*/
129+ /// <summary>
130+ /// Determine if the member is of a type that can be converted using the <see cref="AttributeValueConverter"/> class.
131+ /// </summary>
132+ internal bool IsConvertible { get ; init ; }
133+
134+ /*==========================================================================================================================
135+ | CUSTOM ATTRIBUTES
136+ \-------------------------------------------------------------------------------------------------------------------------*/
137+ /// <summary>
138+ /// Provides a cached list of custom attributes associated with member.
139+ /// </summary>
140+ internal List < Attribute > CustomAttributes {
141+ get {
142+ _customAttributes ??= _attributeProvider . GetCustomAttributes ( true ) . OfType < Attribute > ( ) . ToList ( ) ;
143+ return _customAttributes ;
144+ }
145+ }
146+
147+ } //Class
148+ } //Namespace
0 commit comments