public static void CreateType(DynamicClass dynamicClass) { if (dynamicTypesByName.ContainsKey(dynamicClass.ObjectName)) { throw new InvalidOperationException(string.Format("A type with the name {0} is already loaded. Either change the name of the type or alter it in the database and reinitialize the system", dynamicClass.ObjectName)); } if (assemblyBuilder == null) { throw new InvalidOperationException("The assembly has not been initialized. Call InitializeDynamicClasses before creating new types."); } // Build the type using the given name and make it inherit from BaseObject TypeBuilder tb = moduleBuilder.DefineType( dynamicClass.ObjectName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(BaseObject)); // Build a default constructor for the type so that Newtonsoft knows how to handle it ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); // go over each field on the class and create a property foreach (var field in dynamicClass.Fields) { // if the field is using a system type (or custom model coded in C#), use that if (field.PropertyType != null) { CreateProperty(tb, field.PropertyName, field.PropertyType); } else { // if the field is using a dynamic type, use that and throw exception if it doesn't exist if (!string.IsNullOrEmpty(field.DynamicRuntimeType) && dynamicTypesByName.ContainsKey(field.DynamicRuntimeType)) { CreateProperty(tb, field.PropertyName, dynamicTypesByName[field.DynamicRuntimeType]); } else { throw new ArgumentException(string.Format("No dynamic type exists by the name {0}", field.DynamicRuntimeType)); } } } // now that the properties are attached, create the type and cache it Type objectType = tb.CreateType(); dynamicTypesByName[dynamicClass.ObjectName] = objectType; settersByTypeNameAndProperty[objectType.Name] = PropertyWrapper.CreateFromTypeName(objectType.Name); }
// takes a list of classes and sorts them so that all dependencies will be processed // first. Any cycles will cause an exception to be thrown public static List <DynamicClass> SortDependencyOrder(List <DynamicClass> dynamicClasses) { // Tarjan's algorithm for topological sorting to make sure dynamic classes // that depend on other dynamic classes are initialized first List <DynamicClass> sortedDynamicClasses = new List <DynamicClass>(); Dictionary <string, string> nodeStatus = new Dictionary <string, string>(); foreach (DynamicClass dynamicClass in dynamicClasses) { nodeStatus[dynamicClass.ObjectName] = UNMARKED; } while (nodeStatus.Values.Any(k => k == UNMARKED)) { DynamicClass currentDynamicClass = dynamicClasses.First(dc => dc.ObjectName == nodeStatus.First(s => s.Value == UNMARKED).Key); Visit(currentDynamicClass, nodeStatus, dynamicClasses, sortedDynamicClasses); } return(sortedDynamicClasses); }
static void Main(string[] args) { DynamicClass addressCLass = new DynamicClass() { ObjectName = "Address", Fields = new List<Field>() { new Field() { PropertyName = "Address1", PropertyType = typeof(string) }, new Field() { PropertyName = "Address2", PropertyType = typeof(string) }, new Field() { PropertyName = "PostalCode", PropertyType = typeof(string) } } }; DynamicClass dynamicClass = new DynamicClass() { ObjectName = "Person", Fields = new List<Field>() { new Field() { PropertyName = "FirstName", PropertyType = typeof(string) }, new Field() { PropertyName = "LastName", PropertyType = typeof(string) }, new Field() { PropertyName = "Age", PropertyType = typeof(int) }, new Field() { PropertyName = "Address", DynamicRuntimeType = "Address" } } }; DynamicClassInitializer.InitializeDynamicClasses(new List<DynamicClass>() { addressCLass, dynamicClass }); Example1.Execute(); Example2.Execute(); Example3.Execute(); Example3A.Execute(); Example4.Execute(); Example5.Execute(); Example5A.Execute(); Example6.Execute(); }