private dynamic NextNumber(Type type, PropertyInfoItem prop) { dynamic defValue = ValueHelper.DefaultOf(prop.PropertyType); if (!prop.IsAutonumber) { return(defValue); } dynamic value = defValue; lock (GetLock()) { if (this.Contains(type, prop.PropertyName)) { value = this.GetNext(type, prop.PropertyName, prop.IdentityIncrement); if (value < prop.IdentitySeed) { value = prop.IdentitySeed; this.Update(type, prop.PropertyName, value); } } else if (this.findLastDelegate != null) { MethodInfo numOpsSumGenericMethod = typeof(NumericOperations) .GetMethod("Sum") .MakeGenericMethod(new Type[] { prop.PropertyType }); var last = this.findLastDelegate(type); if (last == null) { value = prop.IdentitySeed; } else { value = numOpsSumGenericMethod.Invoke( null, new object[] { new object[] { prop.Property.GetValue(last), prop.IdentityIncrement } }); } this.Set(type, prop.PropertyName, numOpsSumGenericMethod, value); } } return(value); }
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); // } // } //} }