ObjectViewFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Objects / ObjectViewFactory.cs / 1 / ObjectViewFactory.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       jhutson
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata; 
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses; 
using System.Diagnostics; 
using System.Reflection;
 
namespace System.Data.Objects
{
    /// 
    /// Creates instances of ObjectView that provide a binding list for ObjectQuery results and EntityCollections. 
    /// 
    ///  
    /// The factory methods construct an ObjectView whose generic type parameter (and typed of elements in the binding list) 
    /// is of the same type or a more specific derived type of the generic type of the ObjectQuery or EntityCollection.
    /// The EDM type of the query results or EntityType or the EntityCollection is examined to determine 
    /// the appropriate type to be used.
    /// For example, if you have an ObjectQuery whose generic type is "object", but the EDM result type of the Query maps
    /// to the CLR type "Customer", then the ObjectView returned will specify a generic type of "Customer", and not "object".
    ///  
    internal static class ObjectViewFactory
    { 
        // References to commonly-used generic type definitions. 
        private static readonly Type genericObjectViewType = typeof(ObjectView<>);
 
        private static readonly Type genericObjectViewDataInterfaceType = typeof(IObjectViewData<>);
        private static readonly Type genericObjectViewQueryResultDataType = typeof(ObjectViewQueryResultData<>);
        private static readonly Type genericObjectViewEntityCollectionDataType = typeof(ObjectViewEntityCollectionData<,>);
 
        /// 
        /// Return a list suitable for data binding using the supplied query results. 
        ///  
        /// 
        /// CLR type of query result elements declared by the caller. 
        /// 
        /// 
        /// The EDM type of the query results, used as the primary means of determining the
        /// CLR type of list returned by this method. 
        /// 
        ///  
        /// IEnumerable used to enumerate query results used to populate binding list. 
        /// Must not be null.
        ///  
        /// 
        ///  associated with the query from which results were obtained.
        /// Must not be null.
        ///  
        /// 
        /// True to prevent modifications to the binding list built from the query result; otherwise false. 
        /// Note that other conditions may prevent the binding list from being modified, so a value of false 
        /// supplied for this parameter doesn't necessarily mean that the list will be writable.
        ///  
        /// 
        /// If the query results are composed of entities that only exist in a single ,
        /// the value of this parameter is the single EntitySet.
        /// Otherwise the value of this parameter should be null. 
        /// 
        ///  
        ///  that is suitable for data binding. 
        /// 
        internal static IBindingList CreateViewForQuery(TypeUsage elementEdmTypeUsage, IEnumerable queryResults, ObjectContext objectContext, bool forceReadOnly, EntitySet singleEntitySet) 
        {
            EntityUtil.CheckArgumentNull(queryResults, "queryResults");
            EntityUtil.CheckArgumentNull(objectContext, "objectContext");
 
            Type clrElementType = null;
            TypeUsage ospaceElementTypeUsage = GetOSpaceTypeUsage(elementEdmTypeUsage, objectContext); 
 
            // Map the O-Space EDM type to a CLR type.
            // If the mapping is unsuccessful, fallback to TElement type. 
            if (ospaceElementTypeUsage == null)
            {
                clrElementType = typeof(TElement);
            } 
            {
                clrElementType = GetClrType(ospaceElementTypeUsage.EdmType); 
            } 

            IBindingList objectView; 
            object eventDataSource = objectContext.ObjectStateManager;

            // If the clrElementType matches the declared TElement type, optimize the construction of the ObjectView
            // by avoiding a reflection-based instantiation. 
            if (clrElementType == typeof(TElement))
            { 
                ObjectViewQueryResultData viewData = new ObjectViewQueryResultData((IEnumerable)queryResults, objectContext, forceReadOnly, singleEntitySet); 

                objectView = new ObjectView(viewData, eventDataSource); 
            }
            else if (clrElementType == null)
            {
                ObjectViewQueryResultData viewData = new ObjectViewQueryResultData((IEnumerable)queryResults, objectContext, true, null); 
                objectView = new DataRecordObjectView(viewData, eventDataSource, (RowType)ospaceElementTypeUsage.EdmType, typeof(TElement));
            } 
            else 
            {
                if (!typeof(TElement).IsAssignableFrom(clrElementType)) 
                {
                    throw EntityUtil.ValueInvalidCast(clrElementType, typeof(TElement));
                }
 
                // Use reflection to create an instance of the generic ObjectView and ObjectViewQueryResultData classes,
                // using clrElementType as the value of TElement generic type parameter for both classes. 
 
                Type objectViewDataType = genericObjectViewQueryResultDataType.MakeGenericType(clrElementType);
 
                ConstructorInfo viewDataConstructor = objectViewDataType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                                                                                        null,
                                                                                        new Type[] { typeof(IEnumerable), typeof(ObjectContext), typeof(bool), typeof(EntitySet) },
                                                                                        null); 

                Debug.Assert(viewDataConstructor != null, "ObjectViewQueryResultData constructor not found. Please ensure constructor signature is correct."); 
 
                // Create ObjectViewQueryResultData instance
                object viewData = viewDataConstructor.Invoke(new object[] { queryResults, objectContext, forceReadOnly, singleEntitySet }); 

                // Create ObjectView instance
                objectView = CreateObjectView(clrElementType, objectViewDataType, viewData, eventDataSource);
            } 

            return objectView; 
        } 

        ///  
        /// Return a list suitable for data binding using the supplied EntityCollection
        /// 
        /// 
        /// CLR type of the elements of the EntityCollection. 
        /// 
        ///  
        /// The EntityType of the elements in the collection. 
        /// This should either be the same as the EntityType that corresponds to the CLR TElement type,
        /// or a EntityType derived from the declared EntityCollection element type. 
        /// 
        /// 
        /// The EntityCollection from which a binding list is created.
        ///  
        /// 
        ///  that is suitable for data binding. 
        ///  
        internal static IBindingList CreateViewForEntityCollection(EntityType entityType, EntityCollection entityCollection)
            where TElement : class, IEntityWithRelationships 
        {
            Type clrElementType = null;
            TypeUsage entityTypeUsage = entityType == null ? null : TypeUsage.Create(entityType);
            TypeUsage ospaceElementTypeUsage = GetOSpaceTypeUsage(entityTypeUsage, entityCollection.ObjectContext); 

            // Map the O-Space EDM type to a CLR type. 
            // If the mapping is unsuccessful, fallback to TElement type. 
            if (ospaceElementTypeUsage == null)
            { 
                clrElementType = typeof(TElement);
            }
            else
            { 
                clrElementType = GetClrType(ospaceElementTypeUsage.EdmType);
 
                // A null clrElementType is returned by GetClrType if the EDM type is a RowType with no specific CLR type mapping. 
                // This should not happen when working with EntityCollections, but if it does, fallback to TEntityRef type.
                Debug.Assert(clrElementType != null, "clrElementType has unexpected value of null."); 

                if (clrElementType == null)
                {
                    clrElementType = typeof(TElement); 
                }
            } 
 
            IBindingList objectView;
 
            // If the clrElementType matches the declared TElement type, optimize the construction of the ObjectView
            // by avoiding a reflection-based instantiation.
            if (clrElementType == typeof(TElement))
            { 
                ObjectViewEntityCollectionData viewData = new ObjectViewEntityCollectionData(entityCollection);
                objectView = new ObjectView(viewData, entityCollection); 
            } 
            else
            { 
                if (!typeof(TElement).IsAssignableFrom(clrElementType))
                {
                    throw EntityUtil.ValueInvalidCast(clrElementType, typeof(TElement));
                } 

                // Use reflection to create an instance of the generic ObjectView and ObjectViewEntityCollectionData classes, 
                // using clrElementType as the value of TElement generic type parameter for both classes. 

                Type objectViewDataType = genericObjectViewEntityCollectionDataType.MakeGenericType(clrElementType, typeof(TElement)); 

                ConstructorInfo viewDataConstructor = objectViewDataType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                                                                                        null,
                                                                                        new Type[] { typeof(EntityCollection) }, 
                                                                                        null);
 
                Debug.Assert(viewDataConstructor != null, "ObjectViewEntityCollectionData constructor not found. Please ensure constructor signature is correct."); 

                // Create ObjectViewEntityCollectionData instance 
                object viewData = viewDataConstructor.Invoke(new object[] { entityCollection });

                // Create ObjectView instance
                objectView = CreateObjectView(clrElementType, objectViewDataType, viewData, entityCollection); 
            }
 
            return objectView; 
        }
 
        /// 
        /// Create an ObjectView using reflection.
        /// 
        /// Type to be used for the ObjectView's generic type parameter. 
        /// The type of class that implements the IObjectViewData to be used by the ObjectView.
        /// The IObjectViewData to be used by the ObjectView to access the binding list. 
        /// Event source used by ObjectView for entity and membership changes. 
        /// 
        private static IBindingList CreateObjectView(Type clrElementType, Type objectViewDataType, object viewData, object eventDataSource) 
        {
            Type objectViewType = genericObjectViewType.MakeGenericType(clrElementType);

            Type[] viewDataInterfaces = objectViewDataType.FindInterfaces((Type type, object unusedFilter) => type.Name == genericObjectViewDataInterfaceType.Name, null); 
            Debug.Assert(viewDataInterfaces.Length == 1, "Could not find IObjectViewData interface definition for ObjectViewQueryResultData.");
 
            ConstructorInfo viewConstructor = objectViewType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, 
                                                                            null,
                                                                            new Type[] { viewDataInterfaces[0], typeof(object) }, 
                                                                            null);

            Debug.Assert(viewConstructor != null, "ObjectView constructor not found. Please ensure constructor signature is correct.");
 
            // Create ObjectView instance
            return (IBindingList)viewConstructor.Invoke(new object[] { viewData, eventDataSource }); 
        } 

        ///  
        /// Map the supplied TypeUsage to O-Space.
        /// 
        /// 
        /// The TypeUsage to be mapped to O-Space.  Should either be associated with C-Space or O-Space. 
        /// 
        ///  
        /// ObjectContext used to perform type mapping. 
        /// 
        ///  
        private static TypeUsage GetOSpaceTypeUsage(TypeUsage typeUsage, ObjectContext objectContext)
        {
            TypeUsage ospaceTypeUsage;
 
            if (typeUsage == null || typeUsage.EdmType == null)
            { 
                ospaceTypeUsage = null; 
            }
            else 
            {
                if (typeUsage.EdmType.DataSpace == DataSpace.OSpace)
                {
                    ospaceTypeUsage = typeUsage; 
                }
                else 
                { 
                    Debug.Assert(typeUsage.EdmType.DataSpace == DataSpace.CSpace, String.Format(System.Globalization.CultureInfo.InvariantCulture, "Expected EdmType.DataSpace to be C-Space, but instead it is {0}.", typeUsage.EdmType.DataSpace.ToString()));
 
                    // The ObjectContext is needed to map the EDM TypeUsage from C-Space to O-Space.
                    if (objectContext == null)
                    {
                        ospaceTypeUsage = null; 
                    }
                    else 
                    { 
                        objectContext.EnsureMetadata();
                        ospaceTypeUsage = objectContext.Perspective.MetadataWorkspace.GetOSpaceTypeUsage(typeUsage); 
                    }
                }
            }
 
            return ospaceTypeUsage;
        } 
 
        /// 
        /// Determine CLR Type to be exposed for data binding using the supplied EDM item type. 
        /// 
        /// 
        /// CLR element type declared by the caller.
        /// 
        /// There is no requirement that this method return the same type, or a type compatible with the declared type;
        /// it is merely a suggestion as to which type might be used. 
        ///  
        /// 
        /// The EDM O-Space type of the items in a particular query result. 
        /// 
        /// 
        ///  instance that represents the CLR type that corresponds to the supplied EDM item type;
        /// or null if the EDM type does not map to a CLR type. 
        /// Null is returned in the case where  is a ,
        /// and no CLR type mapping is specified in the RowType metadata. 
        ///  
        private static Type GetClrType(EdmType ospaceEdmType)
        { 
            Type clrType;

            // EDM RowTypes are generally represented by CLR MaterializedDataRecord types
            // that need special handling to properly expose the properties available for binding (using ICustomTypeDescriptor and ITypedList implementations, for example). 
            //
            // However, if the RowType has InitializerMetadata with a non-null CLR Type, 
            // that CLR type should be used to determine the properties available for binding. 
            if (ospaceEdmType.BuiltInTypeKind == BuiltInTypeKind.RowType)
            { 
                RowType itemRowType = (RowType)ospaceEdmType;

                if (itemRowType.InitializerMetadata != null && itemRowType.InitializerMetadata.ClrType != null)
                { 
                    clrType = itemRowType.InitializerMetadata.ClrType;
                } 
                else 
                {
                    // If the generic parameter TElement is not exactly a data record type or object type, 
                    // use it as the CLR type.
                    Type elementType = typeof(TElement);

                    if (typeof(IDataRecord).IsAssignableFrom(elementType) || elementType == typeof(object)) 
                    {
                        // No CLR type mapping exists for this RowType. 
                        clrType = null; 
                    }
                    else 
                    {
                        clrType = typeof(TElement);
                    }
                } 
            }
            else 
            { 
                clrType = ospaceEdmType.ClrType;
 
                // If the CLR type cannot be determined from the EDM type,
                // fallback to the element type declared by the caller.
                if (clrType == null)
                { 
                    clrType = typeof(TElement);
                } 
            } 

            return clrType; 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       jhutson
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata; 
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses; 
using System.Diagnostics; 
using System.Reflection;
 
namespace System.Data.Objects
{
    /// 
    /// Creates instances of ObjectView that provide a binding list for ObjectQuery results and EntityCollections. 
    /// 
    ///  
    /// The factory methods construct an ObjectView whose generic type parameter (and typed of elements in the binding list) 
    /// is of the same type or a more specific derived type of the generic type of the ObjectQuery or EntityCollection.
    /// The EDM type of the query results or EntityType or the EntityCollection is examined to determine 
    /// the appropriate type to be used.
    /// For example, if you have an ObjectQuery whose generic type is "object", but the EDM result type of the Query maps
    /// to the CLR type "Customer", then the ObjectView returned will specify a generic type of "Customer", and not "object".
    ///  
    internal static class ObjectViewFactory
    { 
        // References to commonly-used generic type definitions. 
        private static readonly Type genericObjectViewType = typeof(ObjectView<>);
 
        private static readonly Type genericObjectViewDataInterfaceType = typeof(IObjectViewData<>);
        private static readonly Type genericObjectViewQueryResultDataType = typeof(ObjectViewQueryResultData<>);
        private static readonly Type genericObjectViewEntityCollectionDataType = typeof(ObjectViewEntityCollectionData<,>);
 
        /// 
        /// Return a list suitable for data binding using the supplied query results. 
        ///  
        /// 
        /// CLR type of query result elements declared by the caller. 
        /// 
        /// 
        /// The EDM type of the query results, used as the primary means of determining the
        /// CLR type of list returned by this method. 
        /// 
        ///  
        /// IEnumerable used to enumerate query results used to populate binding list. 
        /// Must not be null.
        ///  
        /// 
        ///  associated with the query from which results were obtained.
        /// Must not be null.
        ///  
        /// 
        /// True to prevent modifications to the binding list built from the query result; otherwise false. 
        /// Note that other conditions may prevent the binding list from being modified, so a value of false 
        /// supplied for this parameter doesn't necessarily mean that the list will be writable.
        ///  
        /// 
        /// If the query results are composed of entities that only exist in a single ,
        /// the value of this parameter is the single EntitySet.
        /// Otherwise the value of this parameter should be null. 
        /// 
        ///  
        ///  that is suitable for data binding. 
        /// 
        internal static IBindingList CreateViewForQuery(TypeUsage elementEdmTypeUsage, IEnumerable queryResults, ObjectContext objectContext, bool forceReadOnly, EntitySet singleEntitySet) 
        {
            EntityUtil.CheckArgumentNull(queryResults, "queryResults");
            EntityUtil.CheckArgumentNull(objectContext, "objectContext");
 
            Type clrElementType = null;
            TypeUsage ospaceElementTypeUsage = GetOSpaceTypeUsage(elementEdmTypeUsage, objectContext); 
 
            // Map the O-Space EDM type to a CLR type.
            // If the mapping is unsuccessful, fallback to TElement type. 
            if (ospaceElementTypeUsage == null)
            {
                clrElementType = typeof(TElement);
            } 
            {
                clrElementType = GetClrType(ospaceElementTypeUsage.EdmType); 
            } 

            IBindingList objectView; 
            object eventDataSource = objectContext.ObjectStateManager;

            // If the clrElementType matches the declared TElement type, optimize the construction of the ObjectView
            // by avoiding a reflection-based instantiation. 
            if (clrElementType == typeof(TElement))
            { 
                ObjectViewQueryResultData viewData = new ObjectViewQueryResultData((IEnumerable)queryResults, objectContext, forceReadOnly, singleEntitySet); 

                objectView = new ObjectView(viewData, eventDataSource); 
            }
            else if (clrElementType == null)
            {
                ObjectViewQueryResultData viewData = new ObjectViewQueryResultData((IEnumerable)queryResults, objectContext, true, null); 
                objectView = new DataRecordObjectView(viewData, eventDataSource, (RowType)ospaceElementTypeUsage.EdmType, typeof(TElement));
            } 
            else 
            {
                if (!typeof(TElement).IsAssignableFrom(clrElementType)) 
                {
                    throw EntityUtil.ValueInvalidCast(clrElementType, typeof(TElement));
                }
 
                // Use reflection to create an instance of the generic ObjectView and ObjectViewQueryResultData classes,
                // using clrElementType as the value of TElement generic type parameter for both classes. 
 
                Type objectViewDataType = genericObjectViewQueryResultDataType.MakeGenericType(clrElementType);
 
                ConstructorInfo viewDataConstructor = objectViewDataType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                                                                                        null,
                                                                                        new Type[] { typeof(IEnumerable), typeof(ObjectContext), typeof(bool), typeof(EntitySet) },
                                                                                        null); 

                Debug.Assert(viewDataConstructor != null, "ObjectViewQueryResultData constructor not found. Please ensure constructor signature is correct."); 
 
                // Create ObjectViewQueryResultData instance
                object viewData = viewDataConstructor.Invoke(new object[] { queryResults, objectContext, forceReadOnly, singleEntitySet }); 

                // Create ObjectView instance
                objectView = CreateObjectView(clrElementType, objectViewDataType, viewData, eventDataSource);
            } 

            return objectView; 
        } 

        ///  
        /// Return a list suitable for data binding using the supplied EntityCollection
        /// 
        /// 
        /// CLR type of the elements of the EntityCollection. 
        /// 
        ///  
        /// The EntityType of the elements in the collection. 
        /// This should either be the same as the EntityType that corresponds to the CLR TElement type,
        /// or a EntityType derived from the declared EntityCollection element type. 
        /// 
        /// 
        /// The EntityCollection from which a binding list is created.
        ///  
        /// 
        ///  that is suitable for data binding. 
        ///  
        internal static IBindingList CreateViewForEntityCollection(EntityType entityType, EntityCollection entityCollection)
            where TElement : class, IEntityWithRelationships 
        {
            Type clrElementType = null;
            TypeUsage entityTypeUsage = entityType == null ? null : TypeUsage.Create(entityType);
            TypeUsage ospaceElementTypeUsage = GetOSpaceTypeUsage(entityTypeUsage, entityCollection.ObjectContext); 

            // Map the O-Space EDM type to a CLR type. 
            // If the mapping is unsuccessful, fallback to TElement type. 
            if (ospaceElementTypeUsage == null)
            { 
                clrElementType = typeof(TElement);
            }
            else
            { 
                clrElementType = GetClrType(ospaceElementTypeUsage.EdmType);
 
                // A null clrElementType is returned by GetClrType if the EDM type is a RowType with no specific CLR type mapping. 
                // This should not happen when working with EntityCollections, but if it does, fallback to TEntityRef type.
                Debug.Assert(clrElementType != null, "clrElementType has unexpected value of null."); 

                if (clrElementType == null)
                {
                    clrElementType = typeof(TElement); 
                }
            } 
 
            IBindingList objectView;
 
            // If the clrElementType matches the declared TElement type, optimize the construction of the ObjectView
            // by avoiding a reflection-based instantiation.
            if (clrElementType == typeof(TElement))
            { 
                ObjectViewEntityCollectionData viewData = new ObjectViewEntityCollectionData(entityCollection);
                objectView = new ObjectView(viewData, entityCollection); 
            } 
            else
            { 
                if (!typeof(TElement).IsAssignableFrom(clrElementType))
                {
                    throw EntityUtil.ValueInvalidCast(clrElementType, typeof(TElement));
                } 

                // Use reflection to create an instance of the generic ObjectView and ObjectViewEntityCollectionData classes, 
                // using clrElementType as the value of TElement generic type parameter for both classes. 

                Type objectViewDataType = genericObjectViewEntityCollectionDataType.MakeGenericType(clrElementType, typeof(TElement)); 

                ConstructorInfo viewDataConstructor = objectViewDataType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                                                                                        null,
                                                                                        new Type[] { typeof(EntityCollection) }, 
                                                                                        null);
 
                Debug.Assert(viewDataConstructor != null, "ObjectViewEntityCollectionData constructor not found. Please ensure constructor signature is correct."); 

                // Create ObjectViewEntityCollectionData instance 
                object viewData = viewDataConstructor.Invoke(new object[] { entityCollection });

                // Create ObjectView instance
                objectView = CreateObjectView(clrElementType, objectViewDataType, viewData, entityCollection); 
            }
 
            return objectView; 
        }
 
        /// 
        /// Create an ObjectView using reflection.
        /// 
        /// Type to be used for the ObjectView's generic type parameter. 
        /// The type of class that implements the IObjectViewData to be used by the ObjectView.
        /// The IObjectViewData to be used by the ObjectView to access the binding list. 
        /// Event source used by ObjectView for entity and membership changes. 
        /// 
        private static IBindingList CreateObjectView(Type clrElementType, Type objectViewDataType, object viewData, object eventDataSource) 
        {
            Type objectViewType = genericObjectViewType.MakeGenericType(clrElementType);

            Type[] viewDataInterfaces = objectViewDataType.FindInterfaces((Type type, object unusedFilter) => type.Name == genericObjectViewDataInterfaceType.Name, null); 
            Debug.Assert(viewDataInterfaces.Length == 1, "Could not find IObjectViewData interface definition for ObjectViewQueryResultData.");
 
            ConstructorInfo viewConstructor = objectViewType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, 
                                                                            null,
                                                                            new Type[] { viewDataInterfaces[0], typeof(object) }, 
                                                                            null);

            Debug.Assert(viewConstructor != null, "ObjectView constructor not found. Please ensure constructor signature is correct.");
 
            // Create ObjectView instance
            return (IBindingList)viewConstructor.Invoke(new object[] { viewData, eventDataSource }); 
        } 

        ///  
        /// Map the supplied TypeUsage to O-Space.
        /// 
        /// 
        /// The TypeUsage to be mapped to O-Space.  Should either be associated with C-Space or O-Space. 
        /// 
        ///  
        /// ObjectContext used to perform type mapping. 
        /// 
        ///  
        private static TypeUsage GetOSpaceTypeUsage(TypeUsage typeUsage, ObjectContext objectContext)
        {
            TypeUsage ospaceTypeUsage;
 
            if (typeUsage == null || typeUsage.EdmType == null)
            { 
                ospaceTypeUsage = null; 
            }
            else 
            {
                if (typeUsage.EdmType.DataSpace == DataSpace.OSpace)
                {
                    ospaceTypeUsage = typeUsage; 
                }
                else 
                { 
                    Debug.Assert(typeUsage.EdmType.DataSpace == DataSpace.CSpace, String.Format(System.Globalization.CultureInfo.InvariantCulture, "Expected EdmType.DataSpace to be C-Space, but instead it is {0}.", typeUsage.EdmType.DataSpace.ToString()));
 
                    // The ObjectContext is needed to map the EDM TypeUsage from C-Space to O-Space.
                    if (objectContext == null)
                    {
                        ospaceTypeUsage = null; 
                    }
                    else 
                    { 
                        objectContext.EnsureMetadata();
                        ospaceTypeUsage = objectContext.Perspective.MetadataWorkspace.GetOSpaceTypeUsage(typeUsage); 
                    }
                }
            }
 
            return ospaceTypeUsage;
        } 
 
        /// 
        /// Determine CLR Type to be exposed for data binding using the supplied EDM item type. 
        /// 
        /// 
        /// CLR element type declared by the caller.
        /// 
        /// There is no requirement that this method return the same type, or a type compatible with the declared type;
        /// it is merely a suggestion as to which type might be used. 
        ///  
        /// 
        /// The EDM O-Space type of the items in a particular query result. 
        /// 
        /// 
        ///  instance that represents the CLR type that corresponds to the supplied EDM item type;
        /// or null if the EDM type does not map to a CLR type. 
        /// Null is returned in the case where  is a ,
        /// and no CLR type mapping is specified in the RowType metadata. 
        ///  
        private static Type GetClrType(EdmType ospaceEdmType)
        { 
            Type clrType;

            // EDM RowTypes are generally represented by CLR MaterializedDataRecord types
            // that need special handling to properly expose the properties available for binding (using ICustomTypeDescriptor and ITypedList implementations, for example). 
            //
            // However, if the RowType has InitializerMetadata with a non-null CLR Type, 
            // that CLR type should be used to determine the properties available for binding. 
            if (ospaceEdmType.BuiltInTypeKind == BuiltInTypeKind.RowType)
            { 
                RowType itemRowType = (RowType)ospaceEdmType;

                if (itemRowType.InitializerMetadata != null && itemRowType.InitializerMetadata.ClrType != null)
                { 
                    clrType = itemRowType.InitializerMetadata.ClrType;
                } 
                else 
                {
                    // If the generic parameter TElement is not exactly a data record type or object type, 
                    // use it as the CLR type.
                    Type elementType = typeof(TElement);

                    if (typeof(IDataRecord).IsAssignableFrom(elementType) || elementType == typeof(object)) 
                    {
                        // No CLR type mapping exists for this RowType. 
                        clrType = null; 
                    }
                    else 
                    {
                        clrType = typeof(TElement);
                    }
                } 
            }
            else 
            { 
                clrType = ospaceEdmType.ClrType;
 
                // If the CLR type cannot be determined from the EDM type,
                // fallback to the element type declared by the caller.
                if (clrType == null)
                { 
                    clrType = typeof(TElement);
                } 
            } 

            return clrType; 
        }
    }
}

// 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