EntityProxyTypeInfo.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Linq; 
using System.Reflection.Emit;
using System.Linq.Expressions; 
using System.Data.Metadata.Edm; 
using System.Data.Common.Utils;
 
namespace System.Data.Objects.Internal
{
    /// 
    /// Contains the Type of a proxy class, along with any behaviors associated with that proxy Type. 
    /// 
    internal sealed class EntityProxyTypeInfo 
    { 
        private readonly Type _proxyType;
        private readonly ClrEntityType _entityType;        // The OSpace entity type that created this proxy info 

        internal const string EntityWrapperFieldName = "_entityWrapper";
        private const string InitializeEntityCollectionsName = "InitializeEntityCollections";
        private readonly FieldInfo _entityWrapperField; 
        private readonly DynamicMethod _initializeCollections;
 
        private readonly Func _baseGetter; 
        private readonly HashSet _propertiesWithBaseGetter;
        private readonly Action _baseSetter; 
        private readonly HashSet _propertiesWithBaseSetter;
        private readonly Func Proxy_GetEntityWrapper;

        private readonly Func _createObject; 

        // An index of relationship metadata strings to an AssociationType 
        // This is used when metadata is not otherwise available to the proxy 
        private readonly Dictionary, AssociationType> _navigationPropertyAssociationTypes;
 
        internal EntityProxyTypeInfo(Type proxyType, ClrEntityType ospaceEntityType, DynamicMethod initializeCollections, List baseGetters, List baseSetters)
        {
            Debug.Assert(proxyType != null, "proxyType must be non-null");
 
            _proxyType = proxyType;
            _entityType = ospaceEntityType; 
 
            _initializeCollections = initializeCollections;
 
            _navigationPropertyAssociationTypes = new Dictionary, AssociationType>();
            foreach (NavigationProperty navigationProperty in ospaceEntityType.NavigationProperties)
            {
                _navigationPropertyAssociationTypes.Add( 
                    new Tuple(
                        navigationProperty.RelationshipType.FullName, 
                        navigationProperty.ToEndMember.Name), 
                    (AssociationType)navigationProperty.RelationshipType);
 
                if (navigationProperty.RelationshipType.Name != navigationProperty.RelationshipType.FullName)
                {
                    // Sometimes there isn't enough metadata to have a container name
                    // Default codegen doesn't qualify names 
                    _navigationPropertyAssociationTypes.Add(
                        new Tuple( 
                            navigationProperty.RelationshipType.Name, 
                            navigationProperty.ToEndMember.Name),
                        (AssociationType)navigationProperty.RelationshipType); 
                }
            }

            _entityWrapperField = proxyType.GetField(EntityWrapperFieldName, BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 

            ParameterExpression Object_Parameter = Expression.Parameter(typeof(object), "proxy"); 
            if (_entityWrapperField != null) 
            {
                Expression> lambda = Expression.Lambda>( 
                        Expression.Field(
                            Expression.Convert(Object_Parameter, _entityWrapperField.DeclaringType), _entityWrapperField),
                            Object_Parameter);
                Func getEntityWrapperDelegate = lambda.Compile(); 
                Proxy_GetEntityWrapper = (object proxy) =>
                { 
                    // This code validates that the wrapper points to the proxy that holds the wrapper. 
                    // This guards against mischief by switching this wrapper out for another one obtained
                    // from a different object. 
                    IEntityWrapper wrapper = ((IEntityWrapper)getEntityWrapperDelegate(proxy));
                    if (wrapper != null && !object.ReferenceEquals(wrapper.Entity, proxy))
                    {
                        throw new InvalidOperationException(System.Data.Entity.Strings.EntityProxyTypeInfo_ProxyHasWrongWrapper); 
                    }
                    return wrapper; 
                }; 
            }
 
            ParameterExpression PropertyName_Parameter = Expression.Parameter(typeof(string), "propertyName");
            MethodInfo baseGetterMethod = proxyType.GetMethod("GetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
            if (baseGetterMethod != null)
            { 
                _baseGetter = Expression.Lambda>(
                    Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseGetterMethod, PropertyName_Parameter), 
                    Object_Parameter, PropertyName_Parameter).Compile(); 
            }
 
            ParameterExpression PropertyValue_Parameter = Expression.Parameter(typeof(object), "propertyName");
            MethodInfo baseSetterMethod = proxyType.GetMethod("SetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(object) }, null);
            if (baseSetterMethod != null)
            { 
                _baseSetter = Expression.Lambda>(
                        Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseSetterMethod, PropertyName_Parameter, PropertyValue_Parameter), 
                        Object_Parameter, PropertyName_Parameter, PropertyValue_Parameter).Compile(); 
            }
 
            _propertiesWithBaseGetter = new HashSet(baseGetters.Select(p => p.Name));
            _propertiesWithBaseSetter = new HashSet(baseSetters.Select(p => p.Name));

            _createObject = LightweightCodeGenerator.CreateConstructor(proxyType) as Func; 
        }
 
        internal object CreateProxyObject() 
        {
            return _createObject(); 
        }

        internal Type ProxyType
        { 
            get { return _proxyType; }
        } 
 
        internal DynamicMethod InitializeEntityCollections
        { 
            get { return _initializeCollections; }
        }

        public Func BaseGetter 
        {
            get { return _baseGetter; } 
        } 

        public bool ContainsBaseGetter(string propertyName) 
        {
            return BaseGetter != null && _propertiesWithBaseGetter.Contains(propertyName);
        }
 
        public bool ContainsBaseSetter(string propertyName)
        { 
            return BaseSetter != null && _propertiesWithBaseSetter.Contains(propertyName); 
        }
 
        public Action BaseSetter
        {
            get { return _baseSetter; }
        } 

        public bool TryGetNavigationPropertyAssociationType(string relationshipName, string targetRoleName, out AssociationType associationType) 
        { 
            return _navigationPropertyAssociationTypes.TryGetValue(new Tuple(relationshipName, targetRoleName), out associationType);
        } 

        public void ValidateType(ClrEntityType ospaceEntityType)
        {
            if (ospaceEntityType != _entityType && ospaceEntityType.HashedDescription != _entityType.HashedDescription) 
            {
                Debug.Assert(ospaceEntityType.ClrType == _entityType.ClrType); 
                throw EntityUtil.DuplicateTypeForProxyType(ospaceEntityType.ClrType); 
            }
        } 

        #region Wrapper on the Proxy

        ///  
        /// Set the proxy object's private entity wrapper field value to the specified entity wrapper object.
        /// The proxy object (representing the wrapped entity) is retrieved from the wrapper itself. 
        ///  
        /// Wrapper object to be referenced by the proxy.
        ///  
        /// The supplied entity wrapper.
        /// This is done so that this method can be more easily composed within lambda expressions (such as in the materializer).
        /// 
        internal IEntityWrapper SetEntityWrapper(IEntityWrapper wrapper) 
        {
            Debug.Assert(wrapper != null, "wrapper must be non-null"); 
            Debug.Assert(wrapper.Entity != null, "proxy must be non-null"); 
            if (_entityWrapperField != null)
            { 
                Debug.Assert(_entityWrapperField.DeclaringType.IsAssignableFrom(wrapper.Entity.GetType()), "proxy is not of the correct Type");

                _entityWrapperField.SetValue(wrapper.Entity, wrapper);
            } 
            return wrapper;
        } 
 
        /// 
        /// Gets the proxy object's entity wrapper field value 
        /// 
        /// 
        /// 
        internal IEntityWrapper GetEntityWrapper(object entity) 
        {
            return Proxy_GetEntityWrapper(entity) as IEntityWrapper; 
        } 

        internal Func EntityWrapperDelegate 
        {
            get { return Proxy_GetEntityWrapper; }
        }
 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

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