public ExpressType(Type type) { Type = type; var entNameAttr = Type.GetCustomAttributes(typeof(ExpressTypeAttribute), false).FirstOrDefault(); #if DEBUG if (entNameAttr == null) { throw new Exception("Express Type is not defined for " + Type.Name); } #endif _typeId = (short)((ExpressTypeAttribute)entNameAttr).EntityTypeId; _expressName = ((ExpressTypeAttribute)entNameAttr).Name; _expressNameUpper = _expressName.ToUpperInvariant(); //it is not an indexed class by default. If it has any indexed properties it is an indexed class but that is detected later on. IndexedClass = false; var dta = type.GetCustomAttributes(typeof(DefinedTypeAttribute), false).FirstOrDefault() as DefinedTypeAttribute; if (dta != null) { _underlyingType = dta.UnderlyingType; if (UnderlyingType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(UnderlyingType)) { var cplType = UnderlyingType.GetGenericArguments()[0]; if (cplType != null) { _underlyingComplexType = cplType; } } } var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); foreach (var propInfo in properties) { var attribute = ((EntityAttributeAttribute[])propInfo.GetCustomAttributes(typeof(EntityAttributeAttribute), false)).FirstOrDefault(); if (attribute == null) { continue; } var metaProperty = new ExpressMetaProperty { PropertyInfo = propInfo, EntityAttribute = attribute }; if (attribute.Order > 0) { _properties.Add(attribute.Order, metaProperty); } else if (attribute.State == EntityAttributeState.Derived) { _derives.Add(metaProperty); } else { var invAttr = propInfo.GetCustomAttributes(typeof(InverseProperty), false)[0] as InverseProperty; metaProperty.InverseAttributeProperty = invAttr; _inverses.Add(metaProperty); } //set up enumerable type if (propInfo.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(propInfo.PropertyType)) { var eType = propInfo.PropertyType; while (typeof(IEnumerable).IsAssignableFrom(eType)) { var genArgs = eType.GetGenericArguments(); if (genArgs.Any()) { eType = genArgs[0]; } else { break; } } metaProperty.EnumerableType = eType; } var isIndexed = propInfo.GetCustomAttributes(typeof(IndexedProperty), false).Any(); metaProperty.IsIndexed = isIndexed; if (!isIndexed) { continue; } //TODO: MC: Review with Steve. This is not true for IfcRelDefinesByProperties.RelatingPropertyDefinition in IFC4 //Debug.Assert(typeof(IPersistEntity).IsAssignableFrom(propInfo.PropertyType) // || typeof(IEnumerable<IPersistEntity>).IsAssignableFrom(propInfo.PropertyType)); //only handles to IPersistEntitiess or collecctions of IPersistEntities are indexable if (_indexedProperties == null) { _indexedProperties = new List <PropertyInfo>(); } if (_indexedValues == null) { _indexedValues = new List <int>(); } _indexedProperties.Add(propInfo); _indexedValues.Add(attribute.Order); IndexedClass = true; //if it has keys it must be an indexed class } //cache enumerable properties foreach (var prop in _properties.Values.Where(prop => typeof(IExpressEnumerable).IsAssignableFrom(prop.PropertyInfo.PropertyType))) { _expressEnumerableProperties.Add(prop); } }