/// <summary>Is this type adorned with any RayAttribute on any property</summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool Marked(Type type)
        {
            PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            if (props.Length < 1)
            {
                return(false);
            }

            foreach (PropertyInfo prop in props)
            {
                RayPropertyAttribute map = prop.GetCustomAttributes <RayPropertyAttribute>(false).FirstOrDefault();

                if (map != null)
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>Gets all the destination field names as a list sorted by their order</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List <string> GetDestinations(Type type, string context = null)
        {
            List <Tuple <uint, string> > rec = new List <Tuple <uint, string> >();

            PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            if (props.Length < 1)
            {
                return(new List <string>());
            }

            foreach (PropertyInfo prop in props)
            {
                RayPropertyAttribute map = null;

                // null context
                if (String.IsNullOrWhiteSpace(context))
                {
                    map     = prop.GetCustomAttributes <RayPropertyAttribute>(false).FirstOrDefault();
                    context = (map != null && !String.IsNullOrWhiteSpace(map.Context)) ? map.Context : null;
                }
                else                 // explicit context
                {
                    map = prop.GetCustomAttributes <RayPropertyAttribute>(false).Where(a => a.Context.Equals(context, StringComparison.Ordinal)).FirstOrDefault();
                }

                if (map == null)
                {
                    continue;
                }

                if (!String.IsNullOrWhiteSpace(map.Destination) && prop.CanRead)
                {
                    rec.Add(new Tuple <uint, string>(map.Order, map.Destination));
                }
            }

            // sort by order
            return(rec.OrderBy(t => t.Item1).Select(t => t.Item2).ToList <string>());
        }
Exemple #3
0
        /// <summary>Parses to FieldSource adorned attributes.</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cursor"></param>
        /// <param name="context">The context to use to parse, can be null and will use the first FieldSource attribute with no context.</param>
        /// <returns></returns>
        private T ParseRecord <T>(SqlDataReader cursor, string context = null) where T : new()
        {
            // valid DB record
            if (cursor == null || !cursor.HasRows)
            {
                return(default(T));
            }

            // get ALL the DB field names lowered
            List <string> fieldNames = Enumerable.Range(0, cursor.FieldCount).Select(cursor.GetName).ToList();            //.ConvertAll( d => d.ToLower() );

            // get all the properties in the class
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            if (props.Length < 1)
            {
                return(default(T));
            }

            T obj = new T();

            // iterate each property
            foreach (PropertyInfo prop in props)
            {
                // can you publicly set the property
                if (!prop.CanWrite)
                {
                    continue;
                }

                // get the properties FieldMap attribute
                List <RayPropertyAttribute> sources = prop.GetCustomAttributes <RayPropertyAttribute>(false).ToList();

                // if there is not field map source, then this property is not read from the CSV
                if (sources == null || sources.Count < 1)
                {
                    continue;
                }

                RayPropertyAttribute map = null;

                // if the context is null - then use the first empty FieldSource
                if (String.IsNullOrWhiteSpace(context))
                {
                    map = sources.Where(s => String.IsNullOrWhiteSpace(s.Context)).FirstOrDefault();
                }
                else
                {
                    map = sources.Where(s => s.Context.Equals(context, StringComparison.Ordinal)).FirstOrDefault();
                }

                if (map == null || String.IsNullOrWhiteSpace(map.Source))
                {
                    continue;
                }

                // verify there is a coresponding DB column name
                if (!fieldNames.Contains(map.Source))
                {
                    continue;
                }

                cursor.Parse <T>(obj, prop, map.Source);
            }

            return(obj);
        }
        /// <summary>Formats the insert statement</summary>
        /// <param name="obj"></param>
        /// <param name="props"></param>
        private SQLiteCommand FormatInsertCommand <T>(T obj, string tableName, IEnumerable <PropertyInfo> props, string ctx)
        {
            // if no table or properties then abort
            if (obj == null || String.IsNullOrWhiteSpace(tableName) || props == null || props.Count() < 1)
            {
                return(null);
            }

            // determine the context type from the object itself
            RayContext ctxType = RayPropertyAttribute.CalculateContext(typeof(T), ctx);

            if (ctxType == RayContext.Error)
            {
                throw new System.Exception("A context was specified by no properties have RayAttribute");
            }

            Dictionary <string, SQLiteParameter> paras = new Dictionary <string, SQLiteParameter>();

            // set the value of each property on the object
            foreach (PropertyInfo prop in props)
            {
                // dict values
                string          propName = null;
                SQLiteParameter param    = null;

                // can you publicly read the property
                if (!prop.CanRead)
                {
                    continue;
                }

                // reject arrays except byte[]
                if (prop.PropertyType.IsArray && prop.PropertyType != typeof(byte[]))
                {
                    continue;
                }

                // reject most generic Lists for now
                if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List <>))
                {
                    continue;
                }

                // property names is determined context type
                if (ctxType == RayContext.PropertyName)
                {
                    propName = prop.Name;
                }
                else if (ctxType == RayContext.Null)
                {
                    // get the properties FieldMap attribute
                    RayPropertyAttribute dest = prop.GetCustomAttributes <RayPropertyAttribute>(false).Where(a => a.IsNullContext).FirstOrDefault();

                    if (dest == null)
                    {
                        continue;
                    }

                    propName = dest.Destination.Trim();
                }

                // get the value
                object value = prop.GetValue(obj);

                // any null values just set to DB Null
                if (value == null)
                {
                    param = new SQLiteParameter($":{propName}", Convert.DBNull);
                }
                // strings
                else if (prop.PropertyType == typeof(string))
                {
                    param = new SQLiteParameter($":{propName}", (value as string));
                }
                // Guids
                else if (prop.PropertyType == typeof(Guid) || prop.PropertyType == typeof(Nullable <Guid>))
                {
                    param = new SQLiteParameter($":{propName}", ((Guid)value).ToString());
                }
                // dates of any kind
                else if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(Nullable <DateTime>))
                {
                    param = new SQLiteParameter($":{propName}", value);
                }
                else if (prop.PropertyType == typeof(DateTimeOffset) || prop.PropertyType == typeof(Nullable <DateTimeOffset>))
                {
                    param = new SQLiteParameter($":{propName}", value);
                }
                // bools are converted to int
                else if (prop.PropertyType == typeof(bool) || prop.PropertyType == typeof(Nullable <bool>))
                {
                    param = new SQLiteParameter($":{propName}", (bool)value ? 1 : 0);
                }
                // enums are int until we create an attribute option to specify text
                else if (prop.PropertyType.IsEnum)
                {
                    param = new SQLiteParameter($":{propName}", (int)value);
                }
                // binary blobs
                else if (prop.PropertyType == typeof(byte[]))
                {
                    param = new SQLiteParameter($":{propName}", value);
                }
                else if (!prop.PropertyType.IsClass)   // everything else thats NOT a class we have not already handled
                {
                    param = new SQLiteParameter($":{propName}", value);
                }

                // add the whole thing to the dictionary
                if (param != null)
                {
                    paras.Add(propName, param);
                }
            }

            // roll the query
            var parameters = paras.Select(n => n.Value.ParameterName).ToArray();

            string query = $"INSERT INTO {tableName} ({String.Join( ",", paras.Keys.ToArray() )}) VALUES ({String.Join( ",", parameters)})";

            SQLiteCommand cmd = new SQLiteCommand(query);

            cmd.CommandType = System.Data.CommandType.Text;
            cmd.Parameters.AddRange(paras.Values.ToArray());

            return(cmd);
        }