public ChildrenSchema(TypeSchema schema, PropertyInfo propInfo, ChildrenAttribute childData) { Trace.WriteLineIf(DebugOutput.Enabled, String.Format(CultureInfo.CurrentCulture, "Creating ChildrenSchema for property {0} and child property {1}", propInfo.Name, childData.PropertyName)); this.schema = schema; this.propInfo = propInfo; this.childData = childData; }
internal void LoadType(Type type) { if (type == null || type == typeof(object)) { return; } List <PropertyInfoItem> typeProps = null; List <PropertyInfo> props = null; List <Type> innerTypes = null; //double-check lock pattern; optemized thread-safe if (!properties.ContainsKey(type.FullName) && GetPropertyTypeCategory(type) == PropertyTypeCategory.Class) { lock (locker) { innerTypes = new List <Type>(); if (!properties.ContainsKey(type.FullName) && GetPropertyTypeCategory(type) == PropertyTypeCategory.Class) { typeProps = new List <PropertyInfoItem>(); // props = System.ComponentModel.TypeDescriptor.GetProperties(type.GetProperties); props = type.GetProperties().Where(s => s.GetAccessors(false).Any()).ToList(); foreach (var prop in props) { var atts = prop.GetCustomAttributes(false).ToArray(); if (atts.OfType <NotMappedAttribute>().Any()) { continue; } PropertyTypeCategory propTypeCategory = GetPropertyTypeCategory(prop.PropertyType); PropertyInfoItem propInfoItem = new PropertyInfoItem() { Type = type, TypeCategory = propTypeCategory, Property = prop, PropertyName = prop.Name, PropertyType = prop.PropertyType, IsGenericType = prop.PropertyType == typeof(object), IsReadOnly = !prop.CanWrite }; var primaryKeyAtt = atts.OfType <PrimaryKeyAttribute>().FirstOrDefault(); propInfoItem.IsPrimaryKey = null != primaryKeyAtt; var foreignKeyAtts = atts.OfType <ForeignKeyAttribute>(); if (foreignKeyAtts.Any()) { propInfoItem.ForeignKeys = foreignKeyAtts.Cast <ForeignKeyAttribute>().ToList(); } var parentKeyAtts = atts.OfType <ParentKeyAttribute>(); if (parentKeyAtts.Any()) { propInfoItem.ParentKeys = parentKeyAtts.Cast <ParentKeyAttribute>().ToList(); } PropertyAttribute propertyAtt = atts.OfType <PropertyAttribute>().FirstOrDefault(); if (null != propertyAtt) { propInfoItem.Cascade = propertyAtt.Cascade; propInfoItem.IsAutonumber = propertyAtt.AutoNumber; //propInfoItem.ForceAutoNumber = propertyAtt.OverrideAutoNumber; propInfoItem.IsIndexed = propertyAtt.Indexed; propInfoItem.ValuePosition = propertyAtt.Position; propInfoItem.IdentityIncrement = propertyAtt.IdentityIncrement; propInfoItem.IdentitySeed = propertyAtt.IdentitySeed; } RequiredAttribute requiredAtt = atts.OfType <RequiredAttribute>().FirstOrDefault(); propInfoItem.IsRequired = null != requiredAtt; UniqueKeyAttribute uniqueKeyAtt = atts.OfType <UniqueKeyAttribute>().FirstOrDefault(); propInfoItem.IsUnique = null != uniqueKeyAtt; MarkupAttribute markupAtt = atts.OfType <MarkupAttribute>().FirstOrDefault(); propInfoItem.IsMarkup = null != markupAtt; CryptoAttribute cryptoAtt = atts.OfType <CryptoAttribute>().FirstOrDefault(); propInfoItem.Encryption = (null != cryptoAtt) ? cryptoAtt.Method : CryptoMethod.None; ChildrenAttribute childrenAtt = atts.OfType <ChildrenAttribute>().FirstOrDefault(); //InheritedAttribute inheritedAtt = (InheritedAttribute)atts // .FirstOrDefault(s => s.GetType() == typeof(InheritedAttribute)); if (null != childrenAtt) { propInfoItem.ReferenceType = PropertyReferenceType.Children; propInfoItem.Cascade = CascadeOptions.Delete; propInfoItem.ChildParentProperty = childrenAtt.RemoteParentProperty; } GenericTypePropertyAttribute genericTypeAtt = atts.OfType <GenericTypePropertyAttribute>().FirstOrDefault(); if (prop.PropertyType == typeof(object) && null != genericTypeAtt) { propInfoItem.GenericTypeProperty = genericTypeAtt.Name; } //setting reference type if (propInfoItem.ReferenceType != PropertyReferenceType.Children) { if (propTypeCategory == PropertyTypeCategory.None) { propInfoItem.ReferenceType = PropertyReferenceType.None; } else if (foreignKeyAtts.Any()) { if (prop.PropertyType.GetProperties() .Where(s => s.PropertyType == type && null != s.GetCustomAttribute <ForeignKeyAttribute>(false)).Any()) { propInfoItem.ReferenceType = PropertyReferenceType.SelfForeign; } else { propInfoItem.ReferenceType = PropertyReferenceType.Foreign; } } else if (parentKeyAtts.Any()) { propInfoItem.ReferenceType = PropertyReferenceType.Parent; } else { propInfoItem.ReferenceType = PropertyReferenceType.Reference; // PropertyDescriptorCollection propTypeProps = TypeDescriptor.GetProperties(prop.PropertyType); var propTypeProps = type.GetProperties().Where(s => s.GetAccessors(false).Any()).ToList(); System.Collections.IEnumerator propTypePropsItems = propTypeProps.GetEnumerator(); foreach (var propTypeProp in propTypeProps) { var propTypePropAtts = propTypeProp.GetCustomAttributes(false).ToArray(); if (propTypePropAtts.OfType <PrimaryKeyAttribute>().Any()) { propInfoItem.ReferenceType = PropertyReferenceType.Complex; propInfoItem.Cascade = CascadeOptions.Delete; break; } } } } if (propTypeCategory == PropertyTypeCategory.Array) { propInfoItem.CollectionItemType = prop.PropertyType.GetElementType(); } else if (propTypeCategory == PropertyTypeCategory.GenericCollection) { propInfoItem.CollectionItemType = prop.PropertyType.GetGenericArguments().FirstOrDefault(); } typeProps.Add(propInfoItem); if (prop.PropertyType != type && ( propTypeCategory == PropertyTypeCategory.Class || propTypeCategory == PropertyTypeCategory.Array || propTypeCategory == PropertyTypeCategory.GenericCollection)) { if (prop.PropertyType.IsArray && prop.PropertyType.GetArrayRank() == 1) { innerTypes.Add(prop.PropertyType.GetElementType()); } else if (null != prop.PropertyType.GetTypeInfo().GetInterface("ICollection")) { innerTypes.Add(prop.PropertyType.GetGenericArguments().FirstOrDefault()); } else if (prop.PropertyType.GetTypeInfo().IsClass) { innerTypes.Add(prop.PropertyType); } } } properties.Add(type.FullName, typeProps); //if there is no PrimaryKey find a property with name Id and make it PrimaryKey if (!typeProps.Any(s => s.IsPrimaryKey)) { var primaryKeyProperty = typeProps.FirstOrDefault(s => s.PropertyName == "Id"); if (primaryKeyProperty != null) { primaryKeyProperty.IsPrimaryKey = true; if (primaryKeyProperty.PropertyType != typeof(string)) { primaryKeyProperty.IsAutonumber = true; } } } } } //after loading all PropertyInfoItems validate them CheckReservedKeywords(type); //load types of inner reference type properties foreach (var innerType in innerTypes) { LoadType(innerType); } } //else if (properties.ContainsKey(type.FullName)) //{ // typeProps = Properties(type.FullName).ToList(); // props = System.ComponentModel.TypeDescriptor.GetProperties(type); // foreach (PropertyDescriptor prop in props) // { // var propItems = typeProps.Select(s => s.Property).ToArray(); // if (propItems.Contains(prop)) // continue; // var refType = GetPropertyTypeCategory(prop.PropertyType); // if (refType == PropertyTypeCategory.Class || // refType == PropertyTypeCategory.Array || // refType == PropertyTypeCategory.GenericCollection) // { // if (prop.PropertyType.IsArray && prop.PropertyType.GetArrayRank() == 1) // LoadType(prop.PropertyType.GetElementType()); // else if (null != prop.PropertyType.GetInterface("ICollection")) // LoadType(prop.PropertyType.GetGenericArguments().FirstOrDefault()); // else if (prop.PropertyType.IsClass) // LoadType(prop.PropertyType); // } // } //} }
public TypeSchema(Type type) { this.type = type; propertySchemas = new Hashtable(); parentSchemas = new Hashtable(); childSchemas = new Hashtable(); Trace.WriteLineIf(DebugOutput.Enabled, "Creating TypeSchema for " + type.FullName); if (!type.IsSubclassOf(typeof(ServerObject))) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0} is not a subclass of ServerObject.", type.FullName)); } if (type.GetCustomAttributes(typeof(TableAttribute), false).Length != 1) { throw new ObjectServerException("Could not locate TableAttribute on type " + type.FullName); } if (!type.IsAbstract) { throw new ObjectServerException(type.FullName + " is not an abstract class"); } tableData = (TableAttribute)type.GetCustomAttributes(typeof(TableAttribute), false)[0]; Debug.Indent(); Trace.WriteLineIf(DebugOutput.Enabled, "TableName = " + tableData.TableName); Trace.WriteLineIf(DebugOutput.Enabled, "PrimaryKey = " + tableData.PrimaryKey); Trace.WriteLineIf(DebugOutput.Enabled, "PrimaryKeyType = " + tableData.KeyType); Trace.WriteLineIf(DebugOutput.Enabled, "DefaultOrder = " + tableData.DefaultOrder); Debug.Unindent(); PropertyInfo keyProperty = type.GetProperty(tableData.PrimaryKey, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (keyProperty == null) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "Could not locate the property {0} which is defined as the property for {1}", tableData.PrimaryKey, type.FullName)); } if (tableData.KeyType == PrimaryKeyType.Identity && keyProperty.PropertyType != typeof(int)) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "KeyType equals PrimaryKeyType.Identity and the property {0}.{1} is not System.Int32", type.FullName, keyProperty.Name)); } if (tableData.KeyType == PrimaryKeyType.Guid && keyProperty.PropertyType != typeof(Guid)) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "KeyType equals PrimaryKeyType.Guid and the property {0}.{1} is not System.Guid", type.FullName, keyProperty.Name)); } foreach (PropertyInfo propInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { Trace.WriteLineIf(DebugOutput.Enabled, "Checking property " + propInfo.Name); if (propInfo.GetCustomAttributes(typeof(ColumnAttribute), false).Length == 1) { if (propInfo.GetIndexParameters().Length != 0) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "Index properties ({0}.{1}) cannot be attributed with ColumnAttribute", type.FullName, propInfo.Name)); } if (!propInfo.CanRead) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must have an accessor", type.FullName, propInfo.Name)); } if (!propInfo.GetGetMethod(true).IsAbstract) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must be abstract", type.FullName, propInfo.Name)); } ColumnAttribute columnData = (ColumnAttribute)propInfo.GetCustomAttributes(typeof(ColumnAttribute), false)[0]; Debug.Indent(); Trace.WriteLineIf(DebugOutput.Enabled, "ColumnName = " + columnData.ColumnName);; Trace.WriteLineIf(DebugOutput.Enabled, "NullValue = " + columnData.NullValue); Debug.Unindent(); if (propInfo.Name == tableData.PrimaryKey && columnData.NullValue != null) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} is marked as the Primary Key and cannot have a NullValue", type.FullName, propInfo.Name)); } propertySchemas.Add(propInfo.Name, new PropertySchema(this, propInfo, columnData)); } else if (propInfo.GetCustomAttributes(typeof(ParentAttribute), false).Length == 1) { if (propInfo.GetIndexParameters().Length != 0) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "Index properties ({0}.{1}) cannot be attributed with ParentAttribute", type.FullName, propInfo.Name)); } if (!propInfo.CanRead) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must have an accessor", type.FullName, propInfo.Name)); } if (!propInfo.GetGetMethod(true).IsAbstract) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must be abstract", type.FullName, propInfo.Name)); } ParentAttribute parentData = (ParentAttribute)propInfo.GetCustomAttributes(typeof(ParentAttribute), false)[0]; if (parentData.DeleteAction == DeleteAction.Null && !parentData.CanBeNull) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} has DeleteAction.Null and CanBeNull is false", type.FullName, propInfo.Name)); } Debug.Indent(); Trace.WriteLineIf(DebugOutput.Enabled, "ColumnName = " + parentData.ColumnName); Trace.WriteLineIf(DebugOutput.Enabled, "ActionOnDelete = " + parentData.DeleteAction); Debug.Unindent(); parentSchemas.Add(propInfo.Name, new ParentSchema(this, propInfo, parentData)); } else if (propInfo.GetCustomAttributes(typeof(ChildrenAttribute), false).Length == 1) { if (propInfo.GetIndexParameters().Length != 0) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "Index properties ({0}.{1}) cannot be attributed with ChildrenAttribute", type.FullName, propInfo.Name)); } if (!propInfo.CanRead) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must have an accessor", type.FullName, propInfo.Name)); } if (propInfo.CanWrite) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must be read only", type.FullName, propInfo.Name)); } if (!propInfo.GetGetMethod(true).IsAbstract) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must be abstract", type.FullName, propInfo.Name)); } if (propInfo.PropertyType != typeof(ServerObjectCollection)) { throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0}.{1} must be of type ServerObjectCollection", type.FullName, propInfo.Name)); } ChildrenAttribute childData = (ChildrenAttribute)propInfo.GetCustomAttributes(typeof(ChildrenAttribute), false)[0]; Debug.Indent(); Trace.WriteLineIf(DebugOutput.Enabled, "ChildType = " + childData.ChildType.FullName); Trace.WriteLineIf(DebugOutput.Enabled, "PropertyName = " + childData.PropertyName); Debug.Unindent(); childSchemas.Add(propInfo.Name, new ChildrenSchema(this, propInfo, childData)); } } proxyType = ProxyBuilder.BuildProxy(type); }