Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / EdmProperty.cs
1 //---------------------------------------------------------------------
2 // <copyright file="EdmProperty.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System.Data.Common;
11 using System.Threading;
12
13 namespace System.Data.Metadata.Edm
14 {
15     /// <summary>
16     /// Represent the edm property class
17     /// </summary>
18     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
19     public sealed class EdmProperty : EdmMember
20     {
21         #region Constructors
22         /// <summary>
23         /// Initializes a new instance of the property class
24         /// </summary>
25         /// <param name="name">name of the property</param>
26         /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
27         /// <exception cref="System.ArgumentNullException">Thrown if name or typeUsage arguments are null</exception>
28         /// <exception cref="System.ArgumentException">Thrown if name argument is empty string</exception>
29         internal EdmProperty(string name, TypeUsage typeUsage)
30             : base(name, typeUsage)
31         {
32             EntityUtil.CheckStringArgument(name, "name");
33             EntityUtil.GenericCheckArgumentNull(typeUsage, "typeUsage");
34         }
35         #endregion
36
37         #region Fields
38         /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
39         internal readonly System.RuntimeMethodHandle PropertyGetterHandle;
40
41         /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
42         internal readonly System.RuntimeMethodHandle PropertySetterHandle;
43
44         /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
45         internal readonly System.RuntimeTypeHandle EntityDeclaringType;
46
47         /// <summary>cached dynamic method to get the property value from a CLR instance</summary> 
48         private Func<object,object> _memberGetter;
49
50         /// <summary>cached dynamic method to set a CLR property value on a CLR instance</summary> 
51         private Action<object,object> _memberSetter;
52         #endregion
53
54         /// <summary>
55         /// Initializes a new OSpace instance of the property class
56         /// </summary>
57         /// <param name="name">name of the property</param>
58         /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
59         /// <param name="propertyInfo">for the property</param>
60         /// <param name="entityDeclaringType">The declaring type of the entity containing the property</param>
61         internal EdmProperty(string name, TypeUsage typeUsage, System.Reflection.PropertyInfo propertyInfo, RuntimeTypeHandle entityDeclaringType)
62             : this(name, typeUsage)
63         {
64             System.Diagnostics.Debug.Assert(name == propertyInfo.Name, "different PropertyName");
65             if (null != propertyInfo)
66             {
67                 System.Reflection.MethodInfo method;
68
69                 method = propertyInfo.GetGetMethod(true); // return public or non-public getter
70                 PropertyGetterHandle = ((null != method) ? method.MethodHandle : default(System.RuntimeMethodHandle));
71
72                 method = propertyInfo.GetSetMethod(true); // return public or non-public getter
73                 PropertySetterHandle = ((null != method) ? method.MethodHandle : default(System.RuntimeMethodHandle));
74
75                 EntityDeclaringType = entityDeclaringType;
76             }
77         }
78
79         /// <summary>
80         /// Returns the kind of the type
81         /// </summary>
82         public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EdmProperty; } }
83
84         /// <summary>
85         /// Returns true if this property is nullable.
86         /// </summary>
87         /// <remarks>
88         /// Nullability in the conceptual model and store model is a simple indication of whether or not
89         /// the property is considered nullable. Nullability in the object model is more complex.
90         /// When using convention based mapping (as usually happens with POCO entities), a property in the
91         /// object model is considered nullable if and only if the underlying CLR type is nullable and
92         /// the property is not part of the primary key.
93         /// When using attribute based mapping (usually used with entities that derive from the EntityObject
94         /// base class), a property is considered nullable if the IsNullable flag is set to true in the
95         /// <see cref="System.Data.Objects.DataClasses.EdmScalarPropertyAttribute"/> attribute. This flag can
96         /// be set to true even if the underlying type is not nullable, and can be set to false even if the
97         /// underlying type is nullable. The latter case happens as part of default code generation when
98         /// a non-nullable property in the conceptual model is mapped to a nullable CLR type such as a string.
99         /// In such a case, the Entity Framework treats the property as non-nullable even though the CLR would
100         /// allow null to be set.
101         /// There is no good reason to set a non-nullable CLR type as nullable in the object model and this
102         /// should not be done even though the attribute allows it.
103         /// </remarks>
104         /// <exception cref="System.InvalidOperationException">Thrown if the setter is called when the EdmProperty instance is in ReadOnly state</exception>
105         public bool Nullable
106         {
107             get
108             {
109                 return (bool)TypeUsage.Facets[DbProviderManifest.NullableFacetName].Value;
110             }
111         }
112
113         /// <summary>
114         /// Returns the default value for this property
115         /// </summary>
116         /// <exception cref="System.InvalidOperationException">Thrown if the setter is called when the EdmProperty instance is in ReadOnly state</exception>
117         public Object DefaultValue
118         {
119             get
120             {
121                 return TypeUsage.Facets[DbProviderManifest.DefaultValueFacetName].Value;
122             }
123         }
124
125         /// <summary>cached dynamic method to get the property value from a CLR instance</summary> 
126         internal Func<object,object> ValueGetter {
127             get { return _memberGetter; }
128             set
129             {
130                 System.Diagnostics.Debug.Assert(null != value, "clearing ValueGetter");
131                 // It doesn't matter which delegate wins, but only one should be jitted
132                 Interlocked.CompareExchange(ref _memberGetter, value, null);
133             }
134         }
135
136         /// <summary>cached dynamic method to set a CLR property value on a CLR instance</summary> 
137         internal Action<object,object> ValueSetter
138         {
139             get { return _memberSetter; }
140             set
141             {
142                 System.Diagnostics.Debug.Assert(null != value, "clearing ValueSetter");
143                 // It doesn't matter which delegate wins, but only one should be jitted
144                 Interlocked.CompareExchange(ref _memberSetter, value, null);
145             }
146         }
147     }
148 }