//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner Microsoft // @backupOwner Microsoft //--------------------------------------------------------------------- using System.Data.Common; using System.Threading; namespace System.Data.Metadata.Edm { /// /// Represent the edm property class /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public sealed class EdmProperty : EdmMember { #region Constructors /// /// Initializes a new instance of the property class /// /// name of the property /// TypeUsage object containing the property type and its facets /// Thrown if name or typeUsage arguments are null /// Thrown if name argument is empty string internal EdmProperty(string name, TypeUsage typeUsage) : base(name, typeUsage) { EntityUtil.CheckStringArgument(name, "name"); EntityUtil.GenericCheckArgumentNull(typeUsage, "typeUsage"); } #endregion #region Fields /// Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd internal readonly System.RuntimeMethodHandle PropertyGetterHandle; /// Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd internal readonly System.RuntimeMethodHandle PropertySetterHandle; /// Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd internal readonly System.RuntimeTypeHandle EntityDeclaringType; /// cached dynamic method to get the property value from a CLR instance private Func _memberGetter; /// cached dynamic method to set a CLR property value on a CLR instance private Action _memberSetter; #endregion /// /// Initializes a new OSpace instance of the property class /// /// name of the property /// TypeUsage object containing the property type and its facets /// for the property /// The declaring type of the entity containing the property 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; } } /// /// Returns the kind of the type /// public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EdmProperty; } } /// /// Returns true if this property is nullable. /// /// /// 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 /// 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. /// /// Thrown if the setter is called when the EdmProperty instance is in ReadOnly state public bool Nullable { get { return (bool)TypeUsage.Facets[DbProviderManifest.NullableFacetName].Value; } } /// /// Returns the default value for this property /// /// Thrown if the setter is called when the EdmProperty instance is in ReadOnly state public Object DefaultValue { get { return TypeUsage.Facets[DbProviderManifest.DefaultValueFacetName].Value; } } /// cached dynamic method to get the property value from a CLR instance internal Func 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); } } /// cached dynamic method to set a CLR property value on a CLR instance internal Action 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); } } } }