예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }