private static void FromArgs(object obj, IEnumerator <object> iter, CRUDInfo info, out bool isNull) { isNull = false; //column names foreach (var local in info.locals) { iter.MoveNext(); local.SetValue(obj, iter.Current); if (iter.Current == null && info.primarySet.Contains(local)) { isNull = true; } } //foreign info foreach (var foreign in info.foreigns) { CRUDInfo fInfo = CRUDInfo.Get(foreign.PropertyType); object inst = fInfo.constructor(); bool isForeignNull; FromArgs(inst, iter, fInfo, out isForeignNull); if (isForeignNull) { inst = null; } foreign.SetValue(obj, inst); } //subquery info foreach (var subquery in info.subqueries) { var attr = subquery.GetCustomAttribute <ForeignMultiKeyAttribute>(); var fInfo = CRUDInfo.Get(subquery.PropertyType.GetGenericArguments()[0]); string table = attr.table; string condition = string.Format(SubquerySQLTemplate, attr.prefix ?? obj.GetType().Name); object[] primaries = info.GetPrimaries(obj); Condition cond = new Condition(condition, primaries); object subqueryObj = fInfo.subqueryConstructor(table, cond); subquery.SetValue(obj, subqueryObj); } }
private CRUDInfo(Type type) { ConstructorInfo info = type.GetConstructor(noTypes); constructor = () => info.Invoke(noArgs); Type subType = typeof(SubQuery <>).MakeGenericType(type); ConstructorInfo subInfo = subType.GetConstructor(subqueryArgs); subqueryConstructor = (table, condition) => subInfo.Invoke(new object[] { table, condition }); foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!prop.HasAttribute <HideAttribute>()) { if (prop.HasAttribute <ForeignMultiKeyAttribute>()) { if (prop.HasAttribute <PrimaryKeyAttribute>()) { throw new ArgumentException("[CRUDService] Primary foreign multi keys are not supported!"); } if (!prop.PropertyType.IsGenericType || prop.PropertyType.GetGenericTypeDefinition() != typeof(SubQuery <>)) { throw new ArgumentException($"[CRUDService] Invalid ForeignMultiKey type for property {prop.Name}. Must be SubQuery<>."); } subqueries.Add(prop); } else { props.Add(prop); if (prop.HasAttribute <PrimaryKeyAttribute>()) { primaries.Add(prop); } if (prop.HasAttribute <IdentityAttribute>()) { identities.Add(prop); } if (prop.HasAttribute <ForeignKeyAttribute>()) { if (prop.HasAttribute <PrimaryKeyAttribute>()) { throw new ArgumentException("[CRUDService] Primary foreign keys are not supported!"); } foreigns.Add(prop); propNames.AddRange( CRUDInfo.Get(prop.PropertyType).primaries.Select( primary => $"{prop.Name}{primary.Name}" ) ); } else { propNames.Add(prop.Name); } } } } locals.AddRange(props); var foreignSet = new HashSet <PropertyInfo>(foreigns); locals.RemoveAll(value => foreignSet.Contains(value)); var identitySet = new HashSet <string>(identities.Select(prop => prop.Name)); createNames.AddRange( propNames.Where(name => !identitySet.Contains(name)) ); var primaryNameSet = new HashSet <string>(primaries.Select(prop => prop.Name)); updateNames.AddRange( propNames.Where(name => !primaryNameSet.Contains(name)) ); primarySet = new HashSet <PropertyInfo>(primaries); }