536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
183 lines
6.3 KiB
C#
183 lines
6.3 KiB
C#
//---------------------------------------------------------------------
|
|
// <copyright file="FieldDescriptor.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// @owner Microsoft
|
|
// @backupOwner Microsoft
|
|
//---------------------------------------------------------------------
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data.Common;
|
|
using System.Data.Objects.DataClasses;
|
|
using System.Data.Metadata.Edm;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
|
|
namespace System.Data.Objects
|
|
{
|
|
internal sealed class FieldDescriptor : PropertyDescriptor
|
|
{
|
|
private readonly EdmProperty _property;
|
|
private readonly Type _fieldType;
|
|
private readonly Type _itemType;
|
|
private readonly bool _isReadOnly;
|
|
|
|
/// <summary>
|
|
/// Construct a new instance of the FieldDescriptor class that describes a property
|
|
/// on items of the supplied type.
|
|
/// </summary>
|
|
/// <param name="itemType">Type of object whose property is described by this FieldDescriptor.</param>
|
|
/// <param name="isReadOnly">
|
|
/// <b>True</b> if property value on item can be modified; otherwise <b>false</b>.
|
|
/// </param>
|
|
/// <param name="property">
|
|
/// EdmProperty that describes the property on the item.
|
|
/// </param>
|
|
internal FieldDescriptor(Type itemType, bool isReadOnly, EdmProperty property)
|
|
: base(property.Name, null)
|
|
{
|
|
_itemType = itemType;
|
|
_property = property;
|
|
_isReadOnly = isReadOnly;
|
|
_fieldType = DetermineClrType(_property.TypeUsage);
|
|
System.Diagnostics.Debug.Assert(_fieldType != null, "FieldDescriptor's CLR type has unexpected value of null.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine a CLR Type to use a property descriptro form an EDM TypeUsage
|
|
/// </summary>
|
|
/// <param name="typeUsage">The EDM TypeUsage containing metadata about the type</param>
|
|
/// <returns>A CLR type that represents that EDM type</returns>
|
|
private Type DetermineClrType(TypeUsage typeUsage)
|
|
{
|
|
Type result = null;
|
|
EdmType edmType = typeUsage.EdmType;
|
|
|
|
switch (edmType.BuiltInTypeKind)
|
|
{
|
|
case BuiltInTypeKind.EntityType:
|
|
case BuiltInTypeKind.ComplexType:
|
|
result = edmType.ClrType;
|
|
break;
|
|
|
|
case BuiltInTypeKind.RefType:
|
|
result = typeof(EntityKey);
|
|
break;
|
|
|
|
case BuiltInTypeKind.CollectionType:
|
|
TypeUsage elementTypeUse = ((CollectionType)edmType).TypeUsage;
|
|
result = DetermineClrType(elementTypeUse);
|
|
result = typeof(IEnumerable<>).MakeGenericType(result);
|
|
break;
|
|
|
|
case BuiltInTypeKind.PrimitiveType:
|
|
case BuiltInTypeKind.EnumType:
|
|
result = edmType.ClrType;
|
|
Facet nullable;
|
|
if (result.IsValueType &&
|
|
typeUsage.Facets.TryGetValue(DbProviderManifest.NullableFacetName, false, out nullable) &&
|
|
((bool)nullable.Value))
|
|
{
|
|
result = typeof(Nullable<>).MakeGenericType(result);
|
|
}
|
|
break;
|
|
|
|
case BuiltInTypeKind.RowType:
|
|
result = typeof(IDataRecord);
|
|
break;
|
|
|
|
default:
|
|
Debug.Fail(string.Format(CultureInfo.CurrentCulture, "The type {0} was not the expected scalar, enumeration, collection, structural, nominal, or reference type.", edmType.GetType()));
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get <see cref="EdmProperty"/> instance associated with this field descriptor.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The <see cref="EdmProperty"/> instance associated with this field descriptor,
|
|
/// or null if there is no EDM property association.
|
|
/// </value>
|
|
internal EdmProperty EdmProperty
|
|
{
|
|
get { return _property; }
|
|
}
|
|
|
|
public override Type ComponentType
|
|
{
|
|
get { return _itemType; }
|
|
}
|
|
public override bool IsReadOnly
|
|
{
|
|
get { return _isReadOnly; }
|
|
}
|
|
public override Type PropertyType
|
|
{
|
|
get { return _fieldType; }
|
|
}
|
|
public override bool CanResetValue(object item)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override object GetValue(object item)
|
|
{
|
|
EntityUtil.CheckArgumentNull(item, "item");
|
|
|
|
if (!_itemType.IsAssignableFrom(item.GetType()))
|
|
{
|
|
throw EntityUtil.IncompatibleArgument();
|
|
}
|
|
|
|
object propertyValue;
|
|
|
|
DbDataRecord dbDataRecord = item as DbDataRecord;
|
|
if (dbDataRecord != null)
|
|
{
|
|
propertyValue = (dbDataRecord.GetValue(dbDataRecord.GetOrdinal(_property.Name)));
|
|
}
|
|
else
|
|
{
|
|
propertyValue = LightweightCodeGenerator.GetValue(_property, item);
|
|
}
|
|
|
|
return propertyValue;
|
|
}
|
|
public override void ResetValue(object item)
|
|
{
|
|
throw EntityUtil.NotSupported();
|
|
}
|
|
|
|
public override void SetValue(object item, object value)
|
|
{
|
|
EntityUtil.CheckArgumentNull(item, "item");
|
|
if (!_itemType.IsAssignableFrom(item.GetType()))
|
|
{
|
|
throw EntityUtil.IncompatibleArgument();
|
|
}
|
|
if (!_isReadOnly)
|
|
{
|
|
LightweightCodeGenerator.SetValue(_property, item, value);
|
|
} // if not entity it must be readonly
|
|
else
|
|
{
|
|
throw EntityUtil.WriteOperationNotAllowedOnReadOnlyBindingList();
|
|
}
|
|
}
|
|
public override bool ShouldSerializeValue(object item)
|
|
{
|
|
return false;
|
|
}
|
|
public override bool IsBrowsable
|
|
{
|
|
get { return true; }
|
|
}
|
|
}
|
|
}
|