Welcome to mirror list, hosted at ThFree Co, Russian Federation.

EdmProperty.cs « Edm « Metadata « Data « System « System.Data.Entity « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b1529dde63395a3c173bb7ae152c60d4927b3f25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//---------------------------------------------------------------------
// <copyright file="EdmProperty.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

using System.Data.Common;
using System.Threading;

namespace System.Data.Metadata.Edm
{
    /// <summary>
    /// Represent the edm property class
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
    public sealed class EdmProperty : EdmMember
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the property class
        /// </summary>
        /// <param name="name">name of the property</param>
        /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
        /// <exception cref="System.ArgumentNullException">Thrown if name or typeUsage arguments are null</exception>
        /// <exception cref="System.ArgumentException">Thrown if name argument is empty string</exception>
        internal EdmProperty(string name, TypeUsage typeUsage)
            : base(name, typeUsage)
        {
            EntityUtil.CheckStringArgument(name, "name");
            EntityUtil.GenericCheckArgumentNull(typeUsage, "typeUsage");
        }
        #endregion

        #region Fields
        /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
        internal readonly System.RuntimeMethodHandle PropertyGetterHandle;

        /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
        internal readonly System.RuntimeMethodHandle PropertySetterHandle;

        /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
        internal readonly System.RuntimeTypeHandle EntityDeclaringType;

        /// <summary>cached dynamic method to get the property value from a CLR instance</summary> 
        private Func<object,object> _memberGetter;

        /// <summary>cached dynamic method to set a CLR property value on a CLR instance</summary> 
        private Action<object,object> _memberSetter;
        #endregion

        /// <summary>
        /// Initializes a new OSpace instance of the property class
        /// </summary>
        /// <param name="name">name of the property</param>
        /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
        /// <param name="propertyInfo">for the property</param>
        /// <param name="entityDeclaringType">The declaring type of the entity containing the property</param>
        internal EdmProperty(string name, TypeUsage typeUsage, System.Reflection.PropertyInfo propertyInfo, RuntimeTypeHandle entityDeclaringType)
            : this(name, typeUsage)
        {
            System.Diagnostics.Debug.Assert(name == propertyInfo.Name, "different PropertyName");
            if (null != propertyInfo)
            {
                System.Reflection.MethodInfo method;

                method = propertyInfo.GetGetMethod(true); // return public or non-public getter
                PropertyGetterHandle = ((null != method) ? method.MethodHandle : default(System.RuntimeMethodHandle));

                method = propertyInfo.GetSetMethod(true); // return public or non-public getter
                PropertySetterHandle = ((null != method) ? method.MethodHandle : default(System.RuntimeMethodHandle));

                EntityDeclaringType = entityDeclaringType;
            }
        }

        /// <summary>
        /// Returns the kind of the type
        /// </summary>
        public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EdmProperty; } }

        /// <summary>
        /// Returns true if this property is nullable.
        /// </summary>
        /// <remarks>
        /// Nullability in the conceptual model and store model is a simple indication of whether or not
        /// the property is considered nullable. Nullability in the object model is more complex.
        /// When using convention based mapping (as usually happens with POCO entities), a property in the
        /// object model is considered nullable if and only if the underlying CLR type is nullable and
        /// the property is not part of the primary key.
        /// When using attribute based mapping (usually used with entities that derive from the EntityObject
        /// base class), a property is considered nullable if the IsNullable flag is set to true in the
        /// <see cref="System.Data.Objects.DataClasses.EdmScalarPropertyAttribute"/> attribute. This flag can
        /// be set to true even if the underlying type is not nullable, and can be set to false even if the
        /// underlying type is nullable. The latter case happens as part of default code generation when
        /// a non-nullable property in the conceptual model is mapped to a nullable CLR type such as a string.
        /// In such a case, the Entity Framework treats the property as non-nullable even though the CLR would
        /// allow null to be set.
        /// There is no good reason to set a non-nullable CLR type as nullable in the object model and this
        /// should not be done even though the attribute allows it.
        /// </remarks>
        /// <exception cref="System.InvalidOperationException">Thrown if the setter is called when the EdmProperty instance is in ReadOnly state</exception>
        public bool Nullable
        {
            get
            {
                return (bool)TypeUsage.Facets[DbProviderManifest.NullableFacetName].Value;
            }
        }

        /// <summary>
        /// Returns the default value for this property
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Thrown if the setter is called when the EdmProperty instance is in ReadOnly state</exception>
        public Object DefaultValue
        {
            get
            {
                return TypeUsage.Facets[DbProviderManifest.DefaultValueFacetName].Value;
            }
        }

        /// <summary>cached dynamic method to get the property value from a CLR instance</summary> 
        internal Func<object,object> ValueGetter {
            get { return _memberGetter; }
            set
            {
                System.Diagnostics.Debug.Assert(null != value, "clearing ValueGetter");
                // It doesn't matter which delegate wins, but only one should be jitted
                Interlocked.CompareExchange(ref _memberGetter, value, null);
            }
        }

        /// <summary>cached dynamic method to set a CLR property value on a CLR instance</summary> 
        internal Action<object,object> ValueSetter
        {
            get { return _memberSetter; }
            set
            {
                System.Diagnostics.Debug.Assert(null != value, "clearing ValueSetter");
                // It doesn't matter which delegate wins, but only one should be jitted
                Interlocked.CompareExchange(ref _memberSetter, value, null);
            }
        }
    }
}