Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        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);
            //        }
            //    }
            //}
        }
Exemplo n.º 3
0
        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);
        }