PocoPropertyAccessorStrategy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Objects / Internal / PocoPropertyAccessorStrategy.cs / 1305376 / PocoPropertyAccessorStrategy.cs

                            using System; 
using System.Collections.Generic;
using System.Text;
using System.Data.Objects.DataClasses;
using System.Diagnostics; 
using System.Reflection;
using System.Data.Metadata.Edm; 
using System.Linq.Expressions; 
using System.Data.Common.Utils;
using System.Data.Mapping; 

namespace System.Data.Objects.Internal
{
    ///  
    /// Implementation of the property accessor strategy that gets and sets values on POCO entities.  That is,
    /// entities that do not implement IEntityWithRelationships. 
    ///  
    internal sealed class PocoPropertyAccessorStrategy : IPropertyAccessorStrategy
    { 
        private static readonly MethodInfo s_AddToCollectionGeneric = typeof(PocoPropertyAccessorStrategy).GetMethod("AddToCollection", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo s_RemoveFromCollectionGeneric = typeof(PocoPropertyAccessorStrategy).GetMethod("RemoveFromCollection", BindingFlags.NonPublic | BindingFlags.Static);

        private object _entity; 

        ///  
        /// Constructs a strategy object to work with the given entity. 
        /// 
        /// The entity to use 
        public PocoPropertyAccessorStrategy(object entity)
        {
            _entity = entity;
        } 

        #region Navigation Property Accessors 
 
        #region GetNavigationPropertyValue
 
        // See IPropertyAccessorStrategy
        public object GetNavigationPropertyValue(RelatedEnd relatedEnd)
        {
            object navPropValue = null; 
            if (relatedEnd != null)
            { 
                if (relatedEnd.TargetAccessor.ValueGetter == null) 
                {
                    Type type = GetDeclaringType(relatedEnd); 
                    PropertyInfo propertyInfo = EntityUtil.GetTopProperty(ref type, relatedEnd.TargetAccessor.PropertyName);
                    if (propertyInfo == null)
                    {
                        throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, type.FullName)); 
                    }
                    EntityProxyFactory factory = new EntityProxyFactory(); 
                    relatedEnd.TargetAccessor.ValueGetter = factory.CreateBaseGetter(type, propertyInfo); 
                }
                try 
                {
                    navPropValue = relatedEnd.TargetAccessor.ValueGetter(_entity);
                }
                catch (Exception ex) 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, _entity.GetType().FullName), ex); 
                } 
            }
            return navPropValue; 
        }

        #endregion
 
        #region SetNavigationPropertyValue
 
        // See IPropertyAccessorStrategy 
        public void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value)
        { 
            if (relatedEnd != null)
            {
                if (relatedEnd.TargetAccessor.ValueSetter == null)
                { 
                    Type type = GetDeclaringType(relatedEnd);
                    PropertyInfo propertyInfo = EntityUtil.GetTopProperty(ref type, relatedEnd.TargetAccessor.PropertyName); 
                    if (propertyInfo == null) 
                    {
                        throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, type.FullName)); 
                    }
                    EntityProxyFactory factory = new EntityProxyFactory();
                    relatedEnd.TargetAccessor.ValueSetter = factory.CreateBaseSetter(type, propertyInfo);
                } 
                try
                { 
                    relatedEnd.TargetAccessor.ValueSetter(_entity, value); 
                }
                catch (Exception ex) 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, _entity.GetType().FullName), ex);
                }
            } 
        }
 
        private static Type GetDeclaringType(RelatedEnd relatedEnd) 
        {
            if (relatedEnd.NavigationProperty != null) 
            {
                EntityType declaringEntityType = (EntityType)relatedEnd.NavigationProperty.DeclaringType;
                ObjectTypeMapping mapping = System.Data.Common.Internal.Materialization.Util.GetObjectMapping(declaringEntityType, relatedEnd.WrappedOwner.Context.MetadataWorkspace);
                return mapping.ClrType.ClrType; 
            }
            else 
            { 
                return relatedEnd.WrappedOwner.IdentityType;
            } 
        }

        private static Type GetNavigationPropertyType(Type entityType, string propertyName)
        { 
            Type navPropType;
            PropertyInfo property = EntityUtil.GetTopProperty(entityType, propertyName); 
            if (property != null) 
            {
                navPropType = property.PropertyType; 
            }
            else
            {
                FieldInfo field = entityType.GetField(propertyName); 
                if (field != null)
                { 
                    navPropType = field.FieldType; 
                }
                else 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(propertyName, entityType.FullName));
                }
            } 
            return navPropType;
        } 
 
        #endregion
 
        #endregion

        #region Collection Navigation Property Accessors
 
        #region CollectionAdd
 
        // See IPropertyAccessorStrategy 
        public void CollectionAdd(RelatedEnd relatedEnd, object value)
        { 
            object entity = _entity;
            try
            {
                object collection = GetNavigationPropertyValue(relatedEnd); 
                if (collection == null)
                { 
                    collection = CollectionCreate(relatedEnd); 
                    SetNavigationPropertyValue(relatedEnd, collection);
                } 
                Debug.Assert(collection != null, "Collection is null");

                // do not call Add if the collection is a RelatedEnd instance
                if (collection == relatedEnd) 
                {
                    return; 
                } 

                if (relatedEnd.TargetAccessor.CollectionAdd == null) 
                {
                    relatedEnd.TargetAccessor.CollectionAdd = CreateCollectionAddFunction(entity.GetType(), relatedEnd.TargetAccessor.PropertyName);
                }
 

                relatedEnd.TargetAccessor.CollectionAdd(collection, value); 
            } 
            catch (Exception ex)
            { 
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, entity.GetType().FullName), ex);
            }
        }
 
        // Helper method to create delegate with property setter
        private static Action CreateCollectionAddFunction(Type type, string propertyName) 
        { 
            Type navPropType = GetNavigationPropertyType(type, propertyName);
            Type elementType = EntityUtil.GetCollectionElementType(navPropType); 
            Type collectionType = typeof(ICollection<>).MakeGenericType(elementType);

            MethodInfo addToCollection = s_AddToCollectionGeneric.MakeGenericMethod(elementType);
            return (Action)addToCollection.Invoke(null, null); 

        } 
 
        private static Action AddToCollection()
        { 
            return (collectionArg, item) =>
                {
                    ICollection collection = (ICollection)collectionArg;
                    Array array = collection as Array; 
                    if (array != null && array.IsFixedSize)
                    { 
                        throw EntityUtil.CannotAddToFixedSizeArray(array); 
                    }
                    collection.Add((T)item); 
                };
        }

        #endregion 

        #region CollectionRemove 
 
        // See IPropertyAccessorStrategy
        public bool CollectionRemove(RelatedEnd relatedEnd, object value) 
        {
            object entity = _entity;
            try
            { 
                object collection = GetNavigationPropertyValue(relatedEnd);
                if (collection != null) 
                { 
                    // do not call Add if the collection is a RelatedEnd instance
                    if (collection == relatedEnd) 
                    {
                        return true;
                    }
 
                    if (relatedEnd.TargetAccessor.CollectionRemove == null)
                    { 
                        relatedEnd.TargetAccessor.CollectionRemove = CreateCollectionRemoveFunction(entity.GetType(), relatedEnd.TargetAccessor.PropertyName); 
                    }
 
                    return relatedEnd.TargetAccessor.CollectionRemove(collection, value);
                }
            }
            catch (Exception ex) 
            {
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, entity.GetType().FullName), ex); 
            } 
            return false;
        } 

        // Helper method to create delegate with property setter
        private static Func CreateCollectionRemoveFunction(Type type, string propertyName)
        { 
            Type navPropType = GetNavigationPropertyType(type, propertyName);
            Type elementType = EntityUtil.GetCollectionElementType(navPropType); 
            Type collectionType = typeof(ICollection<>).MakeGenericType(elementType); 

            MethodInfo removeFromCollection = s_RemoveFromCollectionGeneric.MakeGenericMethod(elementType); 
            return (Func)removeFromCollection.Invoke(null, null);
        }

        private static Func RemoveFromCollection() 
        {
            return (collectionArg, item) => 
            { 
                ICollection collection = (ICollection)collectionArg;
                Array array = collection as Array; 
                if (array != null && array.IsFixedSize)
                {
                    throw EntityUtil.CannotRemoveFromFixedSizeArray(array);
                } 
                return collection.Remove((T)item);
            }; 
        } 

        #endregion 

        #region CollectionCreate

        // See IPropertyAccessorStrategy 
        public object CollectionCreate(RelatedEnd relatedEnd)
        { 
            if (_entity is IEntityWithRelationships) 
            {
                return relatedEnd; 
            }
            else
            {
                if (relatedEnd.TargetAccessor.CollectionCreate == null) 
                {
                    Type entityType = _entity.GetType(); 
                    string propName = relatedEnd.TargetAccessor.PropertyName; 
                    Type navPropType = GetNavigationPropertyType(entityType, propName);
                    relatedEnd.TargetAccessor.CollectionCreate = CreateCollectionCreateDelegate(entityType, navPropType, propName); 
                }
                return relatedEnd.TargetAccessor.CollectionCreate();

            } 
        }
 
        ///  
        /// We only get here if a navigation property getter returns null.  In this case, we try to set the
        /// navigation property to some collection that will work. 
        /// 
        private static Func CreateCollectionCreateDelegate(Type entityType, Type navigationPropertyType, string propName)
        {
            var typeToInstantiate = EntityUtil.DetermineCollectionType(navigationPropertyType); 

            if (typeToInstantiate == null) 
            { 
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToMaterializeArbitaryNavPropType(propName, navigationPropertyType));
            } 

            return Expression.Lambda>(Expression.New(typeToInstantiate)).Compile();
        }
 
        #endregion
 
        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections.Generic;
using System.Text;
using System.Data.Objects.DataClasses;
using System.Diagnostics; 
using System.Reflection;
using System.Data.Metadata.Edm; 
using System.Linq.Expressions; 
using System.Data.Common.Utils;
using System.Data.Mapping; 

namespace System.Data.Objects.Internal
{
    ///  
    /// Implementation of the property accessor strategy that gets and sets values on POCO entities.  That is,
    /// entities that do not implement IEntityWithRelationships. 
    ///  
    internal sealed class PocoPropertyAccessorStrategy : IPropertyAccessorStrategy
    { 
        private static readonly MethodInfo s_AddToCollectionGeneric = typeof(PocoPropertyAccessorStrategy).GetMethod("AddToCollection", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo s_RemoveFromCollectionGeneric = typeof(PocoPropertyAccessorStrategy).GetMethod("RemoveFromCollection", BindingFlags.NonPublic | BindingFlags.Static);

        private object _entity; 

        ///  
        /// Constructs a strategy object to work with the given entity. 
        /// 
        /// The entity to use 
        public PocoPropertyAccessorStrategy(object entity)
        {
            _entity = entity;
        } 

        #region Navigation Property Accessors 
 
        #region GetNavigationPropertyValue
 
        // See IPropertyAccessorStrategy
        public object GetNavigationPropertyValue(RelatedEnd relatedEnd)
        {
            object navPropValue = null; 
            if (relatedEnd != null)
            { 
                if (relatedEnd.TargetAccessor.ValueGetter == null) 
                {
                    Type type = GetDeclaringType(relatedEnd); 
                    PropertyInfo propertyInfo = EntityUtil.GetTopProperty(ref type, relatedEnd.TargetAccessor.PropertyName);
                    if (propertyInfo == null)
                    {
                        throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, type.FullName)); 
                    }
                    EntityProxyFactory factory = new EntityProxyFactory(); 
                    relatedEnd.TargetAccessor.ValueGetter = factory.CreateBaseGetter(type, propertyInfo); 
                }
                try 
                {
                    navPropValue = relatedEnd.TargetAccessor.ValueGetter(_entity);
                }
                catch (Exception ex) 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, _entity.GetType().FullName), ex); 
                } 
            }
            return navPropValue; 
        }

        #endregion
 
        #region SetNavigationPropertyValue
 
        // See IPropertyAccessorStrategy 
        public void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value)
        { 
            if (relatedEnd != null)
            {
                if (relatedEnd.TargetAccessor.ValueSetter == null)
                { 
                    Type type = GetDeclaringType(relatedEnd);
                    PropertyInfo propertyInfo = EntityUtil.GetTopProperty(ref type, relatedEnd.TargetAccessor.PropertyName); 
                    if (propertyInfo == null) 
                    {
                        throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, type.FullName)); 
                    }
                    EntityProxyFactory factory = new EntityProxyFactory();
                    relatedEnd.TargetAccessor.ValueSetter = factory.CreateBaseSetter(type, propertyInfo);
                } 
                try
                { 
                    relatedEnd.TargetAccessor.ValueSetter(_entity, value); 
                }
                catch (Exception ex) 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, _entity.GetType().FullName), ex);
                }
            } 
        }
 
        private static Type GetDeclaringType(RelatedEnd relatedEnd) 
        {
            if (relatedEnd.NavigationProperty != null) 
            {
                EntityType declaringEntityType = (EntityType)relatedEnd.NavigationProperty.DeclaringType;
                ObjectTypeMapping mapping = System.Data.Common.Internal.Materialization.Util.GetObjectMapping(declaringEntityType, relatedEnd.WrappedOwner.Context.MetadataWorkspace);
                return mapping.ClrType.ClrType; 
            }
            else 
            { 
                return relatedEnd.WrappedOwner.IdentityType;
            } 
        }

        private static Type GetNavigationPropertyType(Type entityType, string propertyName)
        { 
            Type navPropType;
            PropertyInfo property = EntityUtil.GetTopProperty(entityType, propertyName); 
            if (property != null) 
            {
                navPropType = property.PropertyType; 
            }
            else
            {
                FieldInfo field = entityType.GetField(propertyName); 
                if (field != null)
                { 
                    navPropType = field.FieldType; 
                }
                else 
                {
                    throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(propertyName, entityType.FullName));
                }
            } 
            return navPropType;
        } 
 
        #endregion
 
        #endregion

        #region Collection Navigation Property Accessors
 
        #region CollectionAdd
 
        // See IPropertyAccessorStrategy 
        public void CollectionAdd(RelatedEnd relatedEnd, object value)
        { 
            object entity = _entity;
            try
            {
                object collection = GetNavigationPropertyValue(relatedEnd); 
                if (collection == null)
                { 
                    collection = CollectionCreate(relatedEnd); 
                    SetNavigationPropertyValue(relatedEnd, collection);
                } 
                Debug.Assert(collection != null, "Collection is null");

                // do not call Add if the collection is a RelatedEnd instance
                if (collection == relatedEnd) 
                {
                    return; 
                } 

                if (relatedEnd.TargetAccessor.CollectionAdd == null) 
                {
                    relatedEnd.TargetAccessor.CollectionAdd = CreateCollectionAddFunction(entity.GetType(), relatedEnd.TargetAccessor.PropertyName);
                }
 

                relatedEnd.TargetAccessor.CollectionAdd(collection, value); 
            } 
            catch (Exception ex)
            { 
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, entity.GetType().FullName), ex);
            }
        }
 
        // Helper method to create delegate with property setter
        private static Action CreateCollectionAddFunction(Type type, string propertyName) 
        { 
            Type navPropType = GetNavigationPropertyType(type, propertyName);
            Type elementType = EntityUtil.GetCollectionElementType(navPropType); 
            Type collectionType = typeof(ICollection<>).MakeGenericType(elementType);

            MethodInfo addToCollection = s_AddToCollectionGeneric.MakeGenericMethod(elementType);
            return (Action)addToCollection.Invoke(null, null); 

        } 
 
        private static Action AddToCollection()
        { 
            return (collectionArg, item) =>
                {
                    ICollection collection = (ICollection)collectionArg;
                    Array array = collection as Array; 
                    if (array != null && array.IsFixedSize)
                    { 
                        throw EntityUtil.CannotAddToFixedSizeArray(array); 
                    }
                    collection.Add((T)item); 
                };
        }

        #endregion 

        #region CollectionRemove 
 
        // See IPropertyAccessorStrategy
        public bool CollectionRemove(RelatedEnd relatedEnd, object value) 
        {
            object entity = _entity;
            try
            { 
                object collection = GetNavigationPropertyValue(relatedEnd);
                if (collection != null) 
                { 
                    // do not call Add if the collection is a RelatedEnd instance
                    if (collection == relatedEnd) 
                    {
                        return true;
                    }
 
                    if (relatedEnd.TargetAccessor.CollectionRemove == null)
                    { 
                        relatedEnd.TargetAccessor.CollectionRemove = CreateCollectionRemoveFunction(entity.GetType(), relatedEnd.TargetAccessor.PropertyName); 
                    }
 
                    return relatedEnd.TargetAccessor.CollectionRemove(collection, value);
                }
            }
            catch (Exception ex) 
            {
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, entity.GetType().FullName), ex); 
            } 
            return false;
        } 

        // Helper method to create delegate with property setter
        private static Func CreateCollectionRemoveFunction(Type type, string propertyName)
        { 
            Type navPropType = GetNavigationPropertyType(type, propertyName);
            Type elementType = EntityUtil.GetCollectionElementType(navPropType); 
            Type collectionType = typeof(ICollection<>).MakeGenericType(elementType); 

            MethodInfo removeFromCollection = s_RemoveFromCollectionGeneric.MakeGenericMethod(elementType); 
            return (Func)removeFromCollection.Invoke(null, null);
        }

        private static Func RemoveFromCollection() 
        {
            return (collectionArg, item) => 
            { 
                ICollection collection = (ICollection)collectionArg;
                Array array = collection as Array; 
                if (array != null && array.IsFixedSize)
                {
                    throw EntityUtil.CannotRemoveFromFixedSizeArray(array);
                } 
                return collection.Remove((T)item);
            }; 
        } 

        #endregion 

        #region CollectionCreate

        // See IPropertyAccessorStrategy 
        public object CollectionCreate(RelatedEnd relatedEnd)
        { 
            if (_entity is IEntityWithRelationships) 
            {
                return relatedEnd; 
            }
            else
            {
                if (relatedEnd.TargetAccessor.CollectionCreate == null) 
                {
                    Type entityType = _entity.GetType(); 
                    string propName = relatedEnd.TargetAccessor.PropertyName; 
                    Type navPropType = GetNavigationPropertyType(entityType, propName);
                    relatedEnd.TargetAccessor.CollectionCreate = CreateCollectionCreateDelegate(entityType, navPropType, propName); 
                }
                return relatedEnd.TargetAccessor.CollectionCreate();

            } 
        }
 
        ///  
        /// We only get here if a navigation property getter returns null.  In this case, we try to set the
        /// navigation property to some collection that will work. 
        /// 
        private static Func CreateCollectionCreateDelegate(Type entityType, Type navigationPropertyType, string propName)
        {
            var typeToInstantiate = EntityUtil.DetermineCollectionType(navigationPropertyType); 

            if (typeToInstantiate == null) 
            { 
                throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToMaterializeArbitaryNavPropType(propName, navigationPropertyType));
            } 

            return Expression.Lambda>(Expression.New(typeToInstantiate)).Compile();
        }
 
        #endregion
 
        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK