/// <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); } }
/// <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); } }