private static string AutoLog <T>(T obj, Type type)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("Parametro 'obj' não pode ser nulo");
            }

            if (type == null)
            {
                throw new ArgumentNullException("Parametro 'type' não pode ser nulo");
            }


            List <PropertyInfo> propertyInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(
                prop => Attribute.IsDefined(prop, typeof(LoggableAttribute))).ToList();

            string result = string.Empty;

            foreach (PropertyInfo pi in propertyInfos)
            {
                LoggableAttribute display = pi.GetCustomAttribute(typeof(LoggableAttribute)) as LoggableAttribute;

                if (pi.GetCustomAttribute(typeof(LoggableSensitiveDataAttribute)) is LoggableSensitiveDataAttribute sensitiveData)
                {
                    continue;
                }

                object value = type.GetProperty(pi.Name).GetValue(obj, null);
                string prefix = string.Empty, sufix = string.Empty;

                if (!string.IsNullOrEmpty(display.PrefixText))
                {
                    prefix += " ";
                }

                if (!string.IsNullOrEmpty(display.SufixText))
                {
                    sufix = " " + sufix;
                }

                string text = GetTextFromType(pi, value);

                result += $"{display.Name}: {prefix}{text}{sufix}, ";
            }

            if (!string.IsNullOrEmpty(result))
            {
                result = result.Remove(result.Length - 2).Insert(0, "(").Insert(result.Length - 1, ")");
            }

            return(result);
        }
        private static string AutoLogUpdate <T>(T obj, Type type, object oldObj)
        {
            if (oldObj == null)
            {
                return("");
            }

            string oldText = string.Empty;
            string newText = string.Empty;

            List <PropertyInfo> propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(
                prop => Attribute.IsDefined(prop, typeof(LoggableAttribute))).ToList();

            foreach (PropertyInfo pi in propertyInfo)
            {
                object newValue = type.GetProperty(pi.Name).GetValue(obj, null);
                object oldValue = type.GetProperty(pi.Name).GetValue(oldObj, null);

                if (newValue != oldValue && (newValue == null || !newValue.Equals(oldValue)))
                {
                    LoggableAttribute display = pi.GetCustomAttribute(typeof(LoggableAttribute)) as LoggableAttribute;

                    string prefix = string.Empty, sufix = string.Empty;
                    if (!string.IsNullOrEmpty(display.PrefixText))
                    {
                        prefix += " ";
                    }

                    if (!string.IsNullOrEmpty(display.SufixText))
                    {
                        sufix = " " + sufix;
                    }

                    string textForOld = GetTextFromType(pi, oldValue);

                    string textForNew = GetTextFromType(pi, newValue);

                    if (pi.GetCustomAttribute(typeof(LoggableSensitiveDataAttribute)) is LoggableSensitiveDataAttribute sensitiveData)
                    {
                        if (!string.IsNullOrEmpty(sensitiveData.MessageOnUpdate))
                        {
                            string text = sensitiveData.MessageOnUpdate.Contains("{0}") ? string.Format(sensitiveData.MessageOnUpdate, display.Name) : sensitiveData.MessageOnUpdate;
                            newText += $"{text}, ";
                        }

                        continue;
                    }

                    oldText += $"{display.Name}: {prefix}{textForOld}{sufix}, ";
                    newText += $"{display.Name}: {prefix}{textForNew}{sufix}, ";
                }
            }

            if (oldText.Length > 0)
            {
                oldText = oldText.Remove(oldText.Length - 2);
                oldText = $"de ({oldText}) ";
            }


            if (newText.Length > 0)
            {
                newText = newText.Remove(newText.Length - 2);
                newText = $"para ({newText})";
            }


            return($"{oldText}{newText}");
        }