developers world

tecnical questionC#

.NET Core 3.1

Data Model Code

0Hancock posted on 2022/02/22 16:17:34

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
#if NewtonJson
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
#else
using System.Text.Json;
#endif
namespace AS.Core.Common
{
    public static class ModelExtensions
    {
        public static readonly object NotExistProperty = new object();
#if !NewtonJson
        private static object GetJsonElementObject(JsonElement el)
        {
            IDictionary<string, object> expandoObject = new ExpandoObject();
            foreach (var obj in el.EnumerateObject())
            {
                var k = obj.Name;
                var value = GetJsonElementValue(obj.Value);
                expandoObject[k] = value;
            }
            return expandoObject;
        }
        private static object GetJsonElementValue(JsonElement el)
        {

            object val = null;
            switch (el.ValueKind)
            {
                case JsonValueKind.Object: val = GetJsonElementObject(el); break;
                case JsonValueKind.True: val = true; break;
                case JsonValueKind.False: val = false; break;
                case JsonValueKind.String: val = el.GetString(); break;
                case JsonValueKind.Number: val = el.GetDecimal(); break;
                case JsonValueKind.Array:
                    {

                        Array objArray = Array.CreateInstance(typeof(object), el.GetArrayLength());
                        int index = 0;
                        var numerator = el.EnumerateArray();
                        foreach (var item in numerator)
                        {
                            objArray.SetValue(GetJsonElementValue(item), index++);
                        }
                        val = objArray;
                    }
                    break;
            }
            return val;
        }
#endif
        internal static object GetValue(this object model, string name)
        {
            
            if (name.Contains("."))
            {
                string rName = name.Substring(0, name.IndexOf("."));
                name = name.Replace(rName + ".", "");
                model = GetValue(model, rName);
                return GetValue(model, name);
            }
            if (model is IDictionary<string, object>)
            {
                var dicData = (IDictionary<string, object>)model;
                if (dicData.ContainsKey(name))
                {
                    object val = dicData[name];
#if !NewtonJson
                    if (val is JsonElement) val = GetJsonElementValue((JsonElement)val);
#endif
                    return val;
                }
            }
#if NewtonJson
            else if (model is JObject)
            {
                var jsonData = (JObject)model;
                name = ToCamelCase(name);

                if (jsonData.ContainsKey(name)) return jsonData.GetValue(name).Value<dynamic>();
            }
#endif
            else
            {
                PropertyInfo prop = model.GetType().GetProperty(name);
                if (prop != null) return prop.GetValue(model);

            }
            return NotExistProperty;
        }
        internal static void SetValue(this IDictionary<string, object> container, string name, object val)
        {
            if (name.Contains("."))
            {
                string rName = name.Substring(0, name.IndexOf("."));
                name = name.Replace(rName + ".", "");
                IDictionary<string, object> uObj = null;
                if (!container.ContainsKey(rName))
                {
                    dynamic obj = new ExpandoObject();
                    uObj = obj;
                    container.Add(rName, obj);
                }
                else
                {
                    uObj = (IDictionary<string, object>)container[rName];
                }
                SetValue(uObj, name, val);
                return;
            }
            name = ToCamelCase(name);
            container[name] = val;
        }
        internal static string ToCamelCase(string s)
        {
            return char.ToLower(s[0]) + s.Substring(1);//.Replace("_", "");
        }
        private static bool IsFinalValue(this object val)
        {
            if (val == null) return true;
            Type type = val.GetType();
            if (type.IsArray) type = type.GetElementType();
            if (type.IsPrimitive
                || val is decimal
                || val is string 
                || val is DateTime 
                || val is Enum 
                || val is Guid) return true;
            return false;
        }
        private static bool IsFinalType(this Type type)
        {
            Type nullableType = Nullable.GetUnderlyingType(type);
            if (nullableType != null) type = nullableType;
            if (type.IsPrimitive
                || typeof(decimal).IsAssignableFrom(type)
                || typeof(string).IsAssignableFrom(type) 
                || typeof(DateTime).IsAssignableFrom(type) 
                || typeof(Enum).IsAssignableFrom(type)
                || typeof(Guid).IsAssignableFrom(type)) return true;
            return false;
        }
        public static dynamic ToDynamic(this object model, Func<Type, string, string> customPropName, Func<Type, object, object> customEnumValue)
        {
            if (model == null) return null;
            if (model.IsFinalValue()) return model;
            if (model is IDictionary<string, object>)
            {
                IDictionary<string, object> pObj = new ExpandoObject();
                foreach (var o in model as IDictionary<string, object>)
                {
                    pObj.SetValue(o.Key, o.Value.ToDynamic(customPropName, customEnumValue) as object);
                }
                return pObj;
            }
            else if (model is System.Collections.IEnumerable)
            {
                List<object> data = new List<object>();
                System.Collections.IEnumerator enumerator = ((System.Collections.IEnumerable)model).GetEnumerator();
                while (enumerator.MoveNext())
                {
                    data.Add(enumerator.Current.ToDynamic(customPropName, customEnumValue));
                }
                return data.ToArray();
            }
            Type type = model.GetType();
            IDictionary<string, object> uObj = new ExpandoObject();
            PropertyInfo[] props = type.GetProperties();
            foreach (var p in props)
            {
                if (p.CanRead)
                {
                    object val = p.GetValue(model);
                    string sName = p.Name;
                    if (val.IsFinalValue())
                    {
                        if (val is Enum && customEnumValue != null)
                        {
                            Type enumType = val.GetType();
                            val = customEnumValue(enumType, val);
                        }
                        if (customPropName != null) sName = customPropName(type, sName);
                        uObj.SetValue(sName, val);
                    }
                    else
                    {
                        uObj.SetValue(sName, val.ToDynamic(customPropName, customEnumValue) as object);
                    }
                }
            }
            return uObj;
        }
        public static void Generate(this object model, Func<Type, string, (string, string)> customSettings)
        {
            Type type = model.GetType();
            PropertyInfo[] props = type.GetProperties();
            Random rnd = new Random();
            foreach (var p in props)
            {
                if (p.CanWrite)
                {
                    object val = null;
                    string mockData = null, dataType = null;
                    (mockData, dataType) = customSettings(type, p.Name);


                    if (p.PropertyType.IsFinalType())
                    {
                        val = DataGenerator.GenerateValue(p.PropertyType, rnd, mockData, dataType);

                    }
                    else if (p.PropertyType.IsArray)
                    {
                        Type elType = p.PropertyType.GetElementType();
                        Array objArray = Array.CreateInstance(elType, rnd.Next(1, 10));
                        for (int i = 0; i < objArray.Length; i++)
                        {
                            object obj = null;
                            if (elType.IsFinalType())
                            {
                                obj = DataGenerator.GenerateValue(elType, rnd, mockData, dataType);
                            }
                            else
                            {
                                obj = Activator.CreateInstance(elType);
                                obj.Generate();
                            }
                            
                            objArray.SetValue(obj, i);
                        }
                        val = objArray;
                    }
                    else if (typeof(IList).IsAssignableFrom(p.PropertyType))
                    {
                        Type elType = p.PropertyType.GenericTypeArguments[0];
                        var constructedListType = typeof(List<>).MakeGenericType(elType);
                        int cnt = rnd.Next(1, 10);
                        var list = (IList)Activator.CreateInstance(constructedListType);
                        
                        for (int i = 0; i < cnt; i++)
                        {
                            object obj = null;
                            if (elType.IsFinalType())
                            {
                                obj = DataGenerator.GenerateValue(elType, rnd, mockData, dataType);
                            }
                            else
                            {
                                obj = Activator.CreateInstance(elType);
                                obj.Generate();
                            }
                            list.Add(obj);
                        }
                        val = list;
                    }
                    else
                    {
                        val = Activator.CreateInstance(p.PropertyType);
                        val.Generate(customSettings);
                    }
                    p.SetValue(model, val);
                }
            }
        }
        private static void FormSerialize(IDictionary<string, object> data, StringBuilder builder, string preKey, bool ignoreIfNull)
        {
            if (data == null) return;
            foreach (var p in data)
            {
                if (p.Value is IDictionary<string, object>)
                {
                    FormSerialize(p.Value as IDictionary<string, object>, builder, (preKey == null ? "" : preKey + ".") + WebUtility.UrlEncode(p.Key), ignoreIfNull);
                }
                else if(p.Value is Array)
                {
                    Array arr = p.Value as Array;
                    for (int i = 0; i < arr.Length; i++)
                    {
                        var val = arr.GetValue(i);
                        if(val is IDictionary<string, object>)
                        {
                            FormSerialize(val as IDictionary<string, object>, builder, WebUtility.UrlEncode(p.Key) + "[" + i + "]", ignoreIfNull);
                        }
                        else
                        {
                            if (ignoreIfNull && val == null) 
                                continue;
                            else 
                                builder.Append((preKey == null ? "" : preKey + ".") + WebUtility.UrlEncode(p.Key) + "[" + i + "]" + "=" + val.UrlEncode() + "&");
                        }
                        
                    }
                }
                else if(ignoreIfNull && p.Value == null) continue;
                else builder.Append((preKey == null ? "" : preKey + ".") + WebUtility.UrlEncode(p.Key) + "=" + p.Value.UrlEncode() + "&");
            }
        }
        private static string UrlEncode(this object val)
        {
            if (val == null) return "";
            return WebUtility.UrlEncode(val.ToString());
        }
        public static string ToFormData(this object obj,bool ignoreIfNull = true, string preKey = null)
        {
            StringBuilder builder = new StringBuilder();
            FormSerialize(obj.ToDynamic() as IDictionary<string, object>, builder, WebUtility.UrlEncode(preKey), ignoreIfNull);
            return builder.ToString().Trim('&');
        }
        private static Array ToArray(this object val)
        {
            Array objArray = null;
            if (val is Array)
            {
                objArray = val as Array;
            }
#if NewtonJson
            else if (val is JArray)
            {
                JArray valArray = (JArray)val;
                objArray = Array.CreateInstance(typeof(object), valArray.Count);
                for (int i = 0; i < valArray.Count; i++)
                {
                    objArray.SetValue(valArray[i], i);
                }
            }
#endif
            return objArray;
        }
        public static void Copy(this object model, object data, bool copiedIfNull, Func<Type, string, string> customPropName, Func<Type, object, object> customEnumValue)
        {
            if (data == null) return;

            Type type = model.GetType();
            PropertyInfo[] props = type.GetProperties();
            foreach (var p in props)
            {
                if (p.CanWrite)
                {
                    string sName = p.Name;
                    if (customPropName != null) sName = customPropName(type, sName);
                    object val = data.GetValue(sName);

                    //try to assign value
                    if (val == null)
                    {
                        if (copiedIfNull)
                        {
                            p.SetValue(model, null);
                        }
                    }
                    else if (val != NotExistProperty)
                    {
                        
                        if (p.PropertyType.IsFinalType())
                        {
                            if (typeof(Enum).IsAssignableFrom(p.PropertyType))
                            {
                                if (customEnumValue != null) val = customEnumValue(p.PropertyType, val);
                                val = Enum.Parse(p.PropertyType, val.ToString());
                            }
                            p.SetValue(model, Convert.ChangeType(val, p.PropertyType));
                        }
                        else if (p.PropertyType.IsArray)
                        {
                            Type elType = p.PropertyType.GetElementType();
                            Array valArray = val.ToArray();
                            if (valArray != null)
                            {
                                Array objArray = Array.CreateInstance(elType, valArray.Length);
                                for (int i = 0; i < objArray.Length; i++)
                                {

                                    if (elType.IsFinalType())
                                    {
                                        val = valArray.GetValue(i);
                                        if (typeof(Enum).IsAssignableFrom(elType))
                                        {
                                            if (customEnumValue != null) val = customEnumValue(elType, val);
                                            val = Enum.Parse(elType, val.ToString());
                                        }
                                        objArray.SetValue(Convert.ChangeType(val, elType), i);
                                    }
                                    else
                                    {
                                        object obj = Activator.CreateInstance(elType);
                                        objArray.SetValue(obj, i);
                                        obj.Copy(valArray.GetValue(i), copiedIfNull, customPropName, customEnumValue);

                                    }

                                }
                                p.SetValue(model, objArray);
                            }


                        }
                        else
                        {
                            object obj = Activator.CreateInstance(p.PropertyType);
                            p.SetValue(model, obj);
                            obj.Copy(val, copiedIfNull, customPropName, customEnumValue);
                        }

                    }


                }
            }
        }
    }
    
}

C#
.NET Core 3.1

Comments

There is no comment
Contact: