public void GenerateModel(IEnumerable<DataSourceBase.DataColumn> columns) { Contract.Requires(columns != null); Contract.Requires(columns.Count() > 0); EmitHelper emit = new EmitHelper(); ModelType = ResolveTypeInternal(Root, emit, columns); try { Assembly assembly = emit.Save(); ModelType = assembly.GetType(ModelType.Name); } catch (Exception ex) { throw new Exception("Unable to save assembly during model generation", ex); } }
private Type ResolveTypeInternal(DataSchemaKey key, EmitHelper emit, IEnumerable<DataSourceBase.DataColumn> columns) { Dictionary<string, Type> properties = new Dictionary<string, Type>(); foreach (DataSchemaKey k in key.Childs) { switch (k.Type) { case DataSchemaKeyType.Container: IEnumerable<DataSchemaKey> ikeys = k.Childs.Where(c => c.Type == DataSchemaKeyType.IteratedValue); List<DataSchemaIteratorValue> ivalues = new List<DataSchemaIteratorValue>(); foreach (DataSchemaKey c in ikeys) { try { DataSchemaIteratorValue value = (DataSchemaIteratorValue)c; ivalues.Add(value); } catch (InvalidCastException) { throw new InvalidDataSchemaException("Invalid DataSchemaKey type for " + c.Name + ", must be DataSchemaIteratorValue.", c); } } if (ivalues.Select(c => c.MappedColumns.Count).Distinct().Count() > 1) throw new InvalidDataSchemaException("All DataSchemaIteratorValue of " + k.Name + " must have the same count of MappedColumn", k); properties.Add(k.Name, ResolveTypeInternal(k, emit, columns)); break; case DataSchemaKeyType.Value: try { DataSchemaValue value = (DataSchemaValue)k; try { DataSourceBase.DataColumn col = columns.Where(c => c.Name == value.MappedColumn).First(); properties.Add(k.Name, col.DataType); } catch { throw new InvalidDataSchemaException("DataColumn " + value.MappedColumn + " was not present in the provided column collection.", value); } } catch (InvalidCastException) { throw new InvalidDataSchemaException("Invalid DataSchemaKey type for " + k.Name + ", must be DataSchemeValue.", k); } break; case DataSchemaKeyType.Iterator: Type t = ResolveTypeInternal(k, emit, columns); properties.Add(k.Name, t.MakeArrayType()); break; case DataSchemaKeyType.IteratedValue: try { DataSchemaIteratorValue value = (DataSchemaIteratorValue)k; foreach (DataSchemaIteratorValueMappedColumn mc in value.MappedColumns) if (columns.Where(c => c.Name == mc.ColumnName).Count() == 0) throw new InvalidDataSchemaException("DataColumn " + mc.ColumnName + " was not present in the provided column collection.", value); IEnumerable<Type> columnsTypes = columns .Where(c => value.MappedColumns.Select(mc => mc.ColumnName) .Contains(c.Name)) .Select(c => c.DataType) .Distinct(); if (columnsTypes.Count() > 1) throw new InvalidDataSchemaException("All mapped columns of " + k.Name + " must have the same datatype.", k); properties.Add(k.Name, columnsTypes.First()); } catch (InvalidCastException) { throw new InvalidDataSchemaException("Invalid DataSchemaKey type for " + k.Name + ", must be DataSchemaIteratorValue.", k); } break; } } Type returnType = emit.CreateType(key.Path, properties); //Contract.Ensures(returnType != null); return returnType; }