Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / EnumType.cs
1 //---------------------------------------------------------------------
2 // <copyright file="EnumType.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Metadata.Edm
11 {
12     using System.Diagnostics;
13     using System.Globalization;
14     using System.Linq;
15
16     /// <summary>
17     /// Represents an enumeration type.
18     /// </summary>
19     public class EnumType : SimpleType
20     {
21         #region Fields
22
23         /// <summary>
24         /// A collection of enumeration members for this enumeration type
25         /// </summary>
26         private readonly ReadOnlyMetadataCollection<EnumMember> _members = 
27             new ReadOnlyMetadataCollection<EnumMember>(new MetadataCollection<EnumMember>());
28
29         /// <summary>
30         /// Indicates whether the enum type is defined as flags (i.e. can be treated as a bit field)
31         /// </summary>
32         private readonly bool _isFlags;
33
34         /// <summary>
35         /// Underlying type of this enumeration type.
36         /// </summary>
37         private readonly PrimitiveType _underlyingType;
38
39         #endregion
40
41         #region Constructors
42         /// <summary>
43         /// Initializes a new instance of the EnumType class. This default constructor is used for bootstraping
44         /// </summary>
45         internal EnumType()
46         {
47             _underlyingType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32);
48             _isFlags = false;
49         }
50
51         /// <summary>
52         /// Initializes a new instance of the EnumType class by using the specified <paramref name="name"/>,
53         /// <paramref name="namespaceName"/> and <paramref name="isFlags"/>.
54         /// </summary>
55         /// <param name="name">The name of this enum type.</param>
56         /// <param name="namespaceName">The namespace this enum type belongs to.</param>
57         /// <param name="isFlags">Indicates whether the enum type is defined as flags (i.e. can be treated as a bit field).</param>
58         /// <param name="underlyingType">Underlying type of this enumeration type.</param>
59         /// <param name="dataSpace">DataSpace this enum type lives in. Can be either CSpace or OSpace</param>
60         /// <exception cref="System.ArgumentNullException">Thrown if name or namespace arguments are null</exception>
61         /// <remarks>Note that enums live only in CSpace.</remarks>
62         internal EnumType(string name, string namespaceName, PrimitiveType underlyingType, bool isFlags, DataSpace dataSpace)
63             : base(name, namespaceName, dataSpace)
64         { 
65             Debug.Assert(underlyingType != null, "underlyingType != null");
66             Debug.Assert(Helper.IsSupportedEnumUnderlyingType(underlyingType.PrimitiveTypeKind), "Unsupported underlying type for enum.");
67             Debug.Assert(dataSpace == DataSpace.CSpace || dataSpace == DataSpace.OSpace, "Enums can be only defined in CSpace or OSpace.");
68
69             _isFlags = isFlags;
70             _underlyingType = underlyingType;
71         }
72
73         /// <summary>
74         /// Initializes a new instance of the EnumType class from CLR enumeration type.
75         /// </summary>
76         /// <param name="clrType">
77         /// CLR enumeration type to create EnumType from.
78         /// </param>
79         /// <remarks>
80         /// Note that this method expects that the <paramref name="clrType"/> is a valid CLR enum type
81         /// whose underlying type is a valid EDM primitive type.
82         /// Ideally this constructor should be protected and internal (Family and Assembly modifier) but
83         /// C# does not support this. In order to not expose this constructor to everyone internal is the
84         /// only option.
85         /// </remarks>
86         internal EnumType(Type clrType) :
87             base(clrType.Name, clrType.Namespace ?? string.Empty, DataSpace.OSpace)
88         {
89             Debug.Assert(clrType != null, "clrType != null");
90             Debug.Assert(clrType.IsEnum, "enum type expected");
91
92             ClrProviderManifest.Instance.TryGetPrimitiveType(clrType.GetEnumUnderlyingType(), out _underlyingType);
93
94             Debug.Assert(_underlyingType != null, "only primitive types expected here.");
95             Debug.Assert(Helper.IsSupportedEnumUnderlyingType(_underlyingType.PrimitiveTypeKind), 
96                 "unsupported CLR types should have been filtered out by .TryGetPrimitiveType() method.");
97
98             _isFlags = clrType.GetCustomAttributes(typeof(FlagsAttribute), false).Any();
99
100             foreach (string name in Enum.GetNames(clrType))
101             {
102                 this.AddMember(
103                     new EnumMember(
104                         name,
105                         Convert.ChangeType(Enum.Parse(clrType, name), clrType.GetEnumUnderlyingType(), CultureInfo.InvariantCulture)));
106             }
107         }
108
109         #endregion
110
111         #region Properties
112
113         /// <summary>
114         /// Returns the kind of the type
115         /// </summary>
116         public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EnumType; } }
117
118         /// <summary>
119         /// Gets a collection of enumeration members for this enumeration type.
120         /// </summary>
121         [MetadataProperty(BuiltInTypeKind.EnumMember, true)]
122         public ReadOnlyMetadataCollection<EnumMember> Members
123         {
124             get { return _members; }
125         }
126
127         /// <summary>
128         /// Gets a value indicating whether the enum type is defined as flags (i.e. can be treated as a bit field)
129         /// </summary>
130         [MetadataProperty(PrimitiveTypeKind.Boolean, false)]
131         public bool IsFlags
132         {
133             get { return _isFlags; }
134         }
135
136         /// <summary>
137         /// Gets the underlying type for this enumeration type.
138         /// </summary>
139         [MetadataProperty(BuiltInTypeKind.PrimitiveType, false)]
140         public PrimitiveType UnderlyingType
141         {
142             get { return _underlyingType; }
143         }
144
145         #endregion
146
147         #region Methods
148
149         /// <summary>
150         /// Sets this item to be readonly, once this is set, the item will never be writable again.
151         /// </summary>
152         internal override void SetReadOnly()
153         {
154             if (!IsReadOnly)
155             {
156                 base.SetReadOnly();
157                 this.Members.Source.SetReadOnly();
158             }
159         }
160
161         /// <summary>
162         /// Adds the specified member to the member collection
163         /// </summary>
164         /// <param name="enumMember">Enumeration member to add to the member collection.</param>
165         internal void AddMember(EnumMember enumMember)
166         {
167             Debug.Assert(enumMember != null, "enumMember != null");
168             Debug.Assert(Helper.IsEnumMemberValueInRange(UnderlyingType.PrimitiveTypeKind, Convert.ToInt64(enumMember.Value, CultureInfo.InvariantCulture)));
169             Debug.Assert(enumMember.Value.GetType() == UnderlyingType.ClrEquivalentType);
170
171             this.Members.Source.Add(enumMember);
172         }
173
174         #endregion
175     }
176
177     /// <summary>
178     /// Represents an enumeration type that has a reference to the backing CLR type.
179     /// </summary>
180     internal sealed class ClrEnumType : EnumType
181     {
182         /// <summary>cached CLR type handle, allowing the Type reference to be GC'd</summary>
183         private readonly System.RuntimeTypeHandle _type;
184
185         private readonly string _cspaceTypeName;
186
187         /// <summary>
188         /// Initializes a new instance of ClrEnumType class with properties from the CLR type.
189         /// </summary>
190         /// <param name="clrType">The CLR type to construct from.</param>
191         /// <param name="cspaceNamespaceName">CSpace namespace name.</param>
192         /// <param name="cspaceTypeName">CSpace type name.</param>
193         internal ClrEnumType(Type clrType, string cspaceNamespaceName, string cspaceTypeName)
194             : base(clrType)  
195         {
196             Debug.Assert(clrType != null, "clrType != null");
197             Debug.Assert(clrType.IsEnum, "enum type expected");
198             Debug.Assert(!String.IsNullOrEmpty(cspaceNamespaceName) && !String.IsNullOrEmpty(cspaceTypeName), "Mapping information must never be null");
199
200             _type = clrType.TypeHandle;
201             _cspaceTypeName = cspaceNamespaceName + "." + cspaceTypeName;
202         }
203
204         /// <summary>
205         /// Gets the clr type backing this enum type.
206         /// </summary>
207         internal override System.Type ClrType
208         {
209             get { return Type.GetTypeFromHandle(_type); }
210         }
211
212         /// <summary>
213         /// Get the full CSpaceTypeName for this enum type.
214         /// </summary>
215         internal string CSpaceTypeName 
216         { 
217             get 
218             { 
219                 return _cspaceTypeName; 
220             } 
221         }
222     }
223 }