private static Type GetListItemType(Type type) { Type type1; if (typeof (Array).IsAssignableFrom(type)) { type1 = type.GetElementType(); } else { PropertyInfo typedIndexer = DataRecordObjectView.GetTypedIndexer(type); type1 = !(typedIndexer != (PropertyInfo) null) ? type : typedIndexer.PropertyType; } return type1; }
/// <summary> /// Return a list suitable for data binding using the supplied query results. /// </summary> /// <typeparam name="TElement"> CLR type of query result elements declared by the caller. </typeparam> /// <param name="elementEdmTypeUsage"> The EDM type of the query results, used as the primary means of determining the CLR type of list returned by this method. </param> /// <param name="queryResults"> IEnumerable used to enumerate query results used to populate binding list. Must not be null. </param> /// <param name="objectContext"> /// <see cref="ObjectContext" /> associated with the query from which results were obtained. Must not be null. /// </param> /// <param name="forceReadOnly"> /// <b>True</b> to prevent modifications to the binding list built from the query result; otherwise <b>false</b> . Note that other conditions may prevent the binding list from being modified, so a value of <b>false</b> supplied for this parameter doesn't necessarily mean that the list will be writable. /// </param> /// <param name="singleEntitySet"> /// If the query results are composed of entities that only exist in a single /// <see /// cref="EntitySet" /> /// , the value of this parameter is the single EntitySet. Otherwise the value of this parameter should be null. /// </param> /// <returns> /// <see cref="IBindingList" /> that is suitable for data binding. /// </returns> internal static IBindingList CreateViewForQuery <TElement>( TypeUsage elementEdmTypeUsage, IEnumerable <TElement> queryResults, ObjectContext objectContext, bool forceReadOnly, EntitySet singleEntitySet) { DebugCheck.NotNull(queryResults); DebugCheck.NotNull(objectContext); Type clrElementType = null; var 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 <TElement>(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)) { var viewData = new ObjectViewQueryResultData <TElement>(queryResults, objectContext, forceReadOnly, singleEntitySet); objectView = new ObjectView <TElement>(viewData, eventDataSource); } else if (clrElementType == null) { var viewData = new ObjectViewQueryResultData <DbDataRecord>(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. var objectViewDataType = _genericObjectViewQueryResultDataType.MakeGenericType(clrElementType); var viewDataConstructor = objectViewDataType.GetConstructor( BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { 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 var viewData = viewDataConstructor.Invoke(new object[] { queryResults, objectContext, forceReadOnly, singleEntitySet }); // Create ObjectView instance objectView = CreateObjectView(clrElementType, objectViewDataType, viewData, eventDataSource); } return(objectView); }
PropertyDescriptorCollection ITypedList.GetItemProperties( PropertyDescriptor[] listAccessors) { PropertyDescriptorCollection descriptorCollection; if (listAccessors == null || listAccessors.Length == 0) { descriptorCollection = this._propertyDescriptorsCache; } else { PropertyDescriptor listAccessor = listAccessors[listAccessors.Length - 1]; FieldDescriptor fieldDescriptor = listAccessor as FieldDescriptor; descriptorCollection = fieldDescriptor == null || fieldDescriptor.EdmProperty == null || fieldDescriptor.EdmProperty.TypeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.RowType ? TypeDescriptor.GetProperties(DataRecordObjectView.GetListItemType(listAccessor.PropertyType)) : MaterializedDataRecord.CreatePropertyDescriptorCollection((StructuralType) fieldDescriptor.EdmProperty.TypeUsage.EdmType, typeof (IDataRecord), true); } return descriptorCollection; }