Esempio n. 1
0
 /// <summary>
 /// Register a custom DynamicTypeInfo on the current types table
 /// </summary>
 /// <param name="typeInfo">info of the type to be register</param>
 public static void RegisterTypeInfo(DynamicTypeInfo typeInfo)
 {
     if (currentTypes.ContainsKey(typeInfo.Name.Replace(".", "_")))
     {
         currentTypes[typeInfo.Name.Replace(".", "_")] = typeInfo;
     }
     else
     {
         currentTypes.Add(typeInfo.Name.Replace(".", "_"), typeInfo);
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Create a new dynamic entity strongly typed class base on a xsd document
        /// </summary>
        /// <param name="entityDefinition">Entity Definition to be parsed</param>
        /// <param name="timestamp">timestamp of the last version of the XSD definition</param>
        /// <returns>return the dynamic entity generate type base on the xsd.</returns>
        public static Type CreateTypeFromEntityDefinition(DatabaseModel ParentModel, EntityModel entityDefinition, DateTime timestamp)
        {
            lock (currentTypes)
            {
                string entityName = entityDefinition.Name;
                //System.Xml.Schema.XmlSchemaSet x;
                //x = new System.Xml.Schema.XmlSchemaSet();
                entityName = entityName.Replace(".", "_");
                Type currentType = DynamicEntityTypeManager.GetType(entityName);
                if (currentType == null)
                {
                    if (moduleBuilder == null)
                    {
                        InitData(ParentModel);
                    }

                    TypeBuilder typeBuilder = GetTypeBuilder(entityName);

                    Type[]             constructorArgTypes     = new Type[] { };
                    ConstructorBuilder constructorBuilder      = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, constructorArgTypes);
                    Type[]             baseConstructorArgTypes = new Type[] { typeof(string) };
                    ILGenerator        ilGenerator             = constructorBuilder.GetILGenerator();
                    ConstructorInfo    baseConstructor         = typeof(DynamicEntityBase).GetConstructor(baseConstructorArgTypes);
                    ilGenerator.Emit(OpCodes.Ldarg_0);
                    ilGenerator.Emit(OpCodes.Ldstr, entityDefinition.Name);
                    ilGenerator.Emit(OpCodes.Call, baseConstructor);
                    ilGenerator.Emit(OpCodes.Ret);

                    // add copy constructor

                    /* constructorArgTypes = new Type[] { typeof(DynamicEntityBase) };
                     * ConstructorBuilder constructorBuilder2 = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, constructorArgTypes);
                     * Type[] baseConstructorArgTypes2 = new Type[] { typeof(DynamicEntityBase) };
                     * ConstructorInfo baseConstructor2 = typeof(DynamicEntityBase).GetConstructor(baseConstructorArgTypes2);
                     * ilGenerator = constructorBuilder2.GetILGenerator();
                     * ilGenerator.Emit(OpCodes.Ldarg_0);
                     * ilGenerator.Emit(OpCodes.Ldarg_1);
                     * ilGenerator.Emit(OpCodes.Call, baseConstructor2);
                     * ilGenerator.Emit(OpCodes.Nop);
                     * ilGenerator.Emit(OpCodes.Nop);
                     * ilGenerator.Emit(OpCodes.Nop);
                     * ilGenerator.Emit(OpCodes.Ret);*/

                    foreach (EntityAttributeModel element in entityDefinition.Attributes)
                    {
                        string propName = element.Name;
                        if (propertNameRegex.IsMatch(propName, 0))
                        {
                            // gets the type code of the property, and ensure that they don't have the namespace to basic schema definition
                            Type propType = DynamicEntityTypeManager.GetClrTypeFromPropertyType(element.AttributeType);

                            CreateProperty(typeBuilder, propName, propType, element.AttributeInfo.IsPrimaryKey, element.AttributeInfo.IsPrimaryKey, null);
                        }
                        else
                        {
                            throw new ArgumentException(
                                      @"Each property name must be 
                            alphanumeric and start with character.");
                        }
                    }

                    // temporary type info for forward reference
                    currentTypes[entityName] = new DynamicTypeInfo(entityName, timestamp, typeBuilder);

                    foreach (EntityRelationshipModel relationship in entityDefinition.Relationships)
                    {
                        string propName = relationship.Name;
                        if (propertNameRegex.IsMatch(propName, 0))
                        {
                            // gets the type code of the property, and ensure that they don't have the namespace to basic schema definition
                            Type        relationshipType       = DynamicEntityTypeManager.GetType(relationship.TargetTableName);
                            EntityModel targetEntityDefinition = ParentModel.Entities.FirstOrDefault(entity => entity.Name == relationship.TargetTableName);
                            bool        isBuildChild           = false;
                            if (relationshipType == null)
                            {
                                if (relationship.TargetTableName == entityDefinition.Name)
                                {
                                    // reference this same type being build
                                    relationshipType = typeBuilder;
                                    isBuildChild     = false;
                                }
                                else
                                {
                                    // create the type look for the model entity definition
                                    relationshipType = CreateTypeFromEntityDefinition(ParentModel, targetEntityDefinition, DateTime.UtcNow);
                                    isBuildChild     = true;
                                }
                            }

                            Type propType = null;
                            List <CustomAttributeBuilder> additionalAttributes = new List <CustomAttributeBuilder>();
                            if (relationship.SupportMultipleRelationships)
                            {
                                propType = typeof(ICollection <>).MakeGenericType(relationshipType);
                                if (!string.IsNullOrEmpty(relationship.InverseRelationshipName))
                                {
                                    EntityRelationshipModel inverseRelation      = targetEntityDefinition.Relationships.FirstOrDefault(rel => rel.Name == relationship.InverseRelationshipName);
                                    ConstructorInfo         attributeConstructor = null;
                                    CustomAttributeBuilder  attributeBuilder     = null;
                                    if (inverseRelation != null)
                                    {
                                        attributeConstructor = typeof(System.ComponentModel.DataAnnotations.Schema.InversePropertyAttribute).GetConstructor(new Type[] { typeof(string) });
                                        attributeBuilder     = new CustomAttributeBuilder(attributeConstructor, new object[] { relationship.InverseRelationshipName }, new FieldInfo[] { }, new object[] { });
                                        additionalAttributes.Add(attributeBuilder);
                                    }
                                }
                            }
                            else
                            {
                                propType = relationshipType;
                                if (!string.IsNullOrEmpty(relationship.InverseRelationshipName))
                                {
                                    EntityRelationshipModel inverseRelation      = targetEntityDefinition.Relationships.FirstOrDefault(rel => rel.Name == relationship.InverseRelationshipName);
                                    ConstructorInfo         attributeConstructor = null;
                                    CustomAttributeBuilder  attributeBuilder     = null;
                                    if (inverseRelation != null)
                                    {
                                        attributeConstructor = typeof(System.ComponentModel.DataAnnotations.Schema.InversePropertyAttribute).GetConstructor(new Type[] { typeof(string) });
                                        attributeBuilder     = new CustomAttributeBuilder(attributeConstructor, new object[] { relationship.InverseRelationshipName }, new FieldInfo[] { }, new object[] { });
                                        additionalAttributes.Add(attributeBuilder);
                                    }

                                    //create foreign key field
                                    EntityAttributeModel targetKey = targetEntityDefinition.Attributes.FirstOrDefault(a => a.AttributeInfo.IsPrimaryKey);
                                    if (targetKey != null)
                                    {
                                        string fkFieldName = relationship.Name + "_FK";
                                        attributeConstructor = typeof(System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute).GetConstructor(new Type[] { typeof(string) });
                                        if (inverseRelation.SupportMultipleRelationships)
                                        {
                                            CreateProperty(typeBuilder, fkFieldName, DynamicEntityTypeManager.GetClrTypeFromPropertyType(targetKey.AttributeType), false, true, null);
                                            attributeBuilder = new CustomAttributeBuilder(attributeConstructor, new object[] { fkFieldName }, new FieldInfo[] { }, new object[] { });
                                        }
                                        else
                                        {
                                            attributeBuilder = new CustomAttributeBuilder(attributeConstructor, new object[] { targetKey.Name }, new FieldInfo[] { }, new object[] { });
                                        }
                                        additionalAttributes.Add(attributeBuilder);
                                    }
                                }
                            }

                            if (propType == null)
                            {
                                throw new NullReferenceException(string.Format("The relationship {0} type can't be determinate", relationship.Name));
                            }

                            CreateProperty(typeBuilder, propName, propType, false, !isBuildChild, additionalAttributes);
                        }
                        else
                        {
                            throw new ArgumentException(
                                      @"Each property name must be 
                            alphanumeric and start with character.");
                        }
                    }

                    Type newType = typeBuilder.CreateType();

                    //currentTypes[resourceFriendlyName] = newType;
                    currentTypes[entityName] = new DynamicTypeInfo(entityName, timestamp, newType);

                    //assemblyBuilder.Save("BLTypeManagerTest.dll");

                    return(newType);
                }
                return(currentType);
            }
        }