private static IEnumerable <Method> GetValidMethods(DecoratorDecription decorator, BuilderType[] methodParameters, BuilderType @class)
        {
            return(@class.Methods.Where(x =>
            {
                if (x.IsPropertyGetterSetter)
                {
                    return false;
                }

                if (!decorator.TargetMethodFilter.Static && x.IsStatic)
                {
                    return false;
                }

                if (!decorator.TargetMethodFilter.Instanced && !x.IsStatic)
                {
                    return false;
                }

                if (
                    decorator.TargetMethodFilter.Protected && !x.IsProtected &&
                    decorator.TargetMethodFilter.Public && !x.IsPublic &&
                    decorator.TargetMethodFilter.Private && !x.IsPrivate &&
                    decorator.TargetMethodFilter.Internal && !x.IsInternal)
                {
                    return false;
                }

                if (decorator.TargetMethodFilter.ReturnTypeNames.Length > 0 && !decorator.TargetMethodFilter.ReturnTypeNames.Any(y => y == x.Fullname))
                {
                    return false;
                }

                if (decorator.TargetMethodFilter.ParameterMatch)
                {
                    if (!decorator.TargetMethodFilter.ParameterStrict && decorator.TargetMethodFilter.Parameters.Length > 0 && !x.Parameters.AreReferenceAssignable(methodParameters))
                    {
                        return false;
                    }
                    else if (decorator.TargetMethodFilter.ParameterStrict && decorator.TargetMethodFilter.Parameters.Length > 0 && !x.Parameters.SequenceEqual(methodParameters))
                    {
                        return false;
                    }
                }

                if (x.IsGenerated)
                {
                    return false;
                }

                if (!string.IsNullOrEmpty(decorator.TargetMethodFilter.Name) && !Regex.IsMatch(x.Name, decorator.TargetMethodFilter.Name == "*" ? "[a-zA-Z].*" : decorator.TargetMethodFilter.Name, RegexOptions.Singleline))
                {
                    return false;
                }

                return true;
            }));
        }
        private static IEnumerable <Property> GetValidProperties(DecoratorDecription decorator, BuilderType @class)
        {
            return(@class.Properties.Where(x =>
            {
                if (!decorator.TargetPropertyFilter.Static && x.IsStatic)
                {
                    return false;
                }

                if (!decorator.TargetPropertyFilter.Instanced && !x.IsStatic)
                {
                    return false;
                }

                if (
                    decorator.TargetPropertyFilter.Protected && !x.IsProtected &&
                    decorator.TargetPropertyFilter.Public && !x.IsPublic &&
                    decorator.TargetPropertyFilter.Private && !x.IsPrivate &&
                    decorator.TargetPropertyFilter.Internal && !x.IsInternal)
                {
                    return false;
                }

                if (decorator.TargetPropertyFilter.ReturnTypeNames.Length > 0 && !decorator.TargetPropertyFilter.ReturnTypeNames.Any(y => y == x.ReturnType.Fullname))
                {
                    return false;
                }

                if (x.IsGenerated)
                {
                    return false;
                }

                if (!string.IsNullOrEmpty(decorator.TargetPropertyFilter.Name) && !Regex.IsMatch(x.Name, decorator.TargetMethodFilter.Name == "*" ? "[a-zA-Z].*" : decorator.TargetPropertyFilter.Name, RegexOptions.Singleline))
                {
                    return false;
                }

                return true;
            }));
        }
        private static void ImplementDecorator(Builder builder, DecoratorDecription decorator, IEnumerable <BuilderType> classes)
        {
            var attribute       = builder.GetType(decorator.TypeName);
            var attributeTarget = attribute.CustomAttributes.FirstOrDefault(x => x.Fullname == "System.AttributeUsageAttribute");
            var parameterValues = decorator.Parameters.Select <DecoratorDecriptionParameter, object>(x =>
            {
                var result = ConvertPropertyType(builder, x.TypeName, x.Value);
                if (result != null)
                {
                    return(result);
                }

                if (x.TypeName.EndsWith("[]"))
                {
                    throw new NotSupportedException($"Arrays are not supported by the attribute decorator: " + x.TypeName);
                }

                var type = builder.GetType(x.TypeName);

                if (type.IsEnum)
                {
                    var underlyingType = type.EnumUnderlyingType;
                    return(ConvertPropertyType(builder, underlyingType.Fullname, x.Value));
                }

                throw new NotSupportedException($"The attribute decorator does not support this type: " + x.TypeName);
            })
                                  .ToArray();
            var methodParameters = decorator.TargetMethodFilter.Parameters.Select(x => builder.GetType(x)).ToArray();

            AttributeTargets attributeTargets = AttributeTargets.All;

            if (attributeTarget != null)
            {
                Enum.TryParse(attributeTarget.ConstructorArguments[0].Value?.ToString(), out attributeTargets);
            }

            var allowMultiple = false;

            if (attributeTarget.Properties.TryGetValue("AllowMultiple", out CustomAttributeArgument customAttributeArgument))
            {
                allowMultiple = (bool)customAttributeArgument.Value;
            }

            foreach (var @class in classes)
            {
                if (decorator.DecorateClass && @class.CustomAttributes.Add(attribute, parameterValues))
                {
                    builder.Log(LogTypes.Info, "- Decorating Class " + @class);
                }

                if (decorator.DecorateMethod)
                {
                    foreach (var method in GetValidMethods(decorator, methodParameters, @class))
                    {
                        if (method.CustomAttributes.Add(attribute, parameterValues))
                        {
                            builder.Log(LogTypes.Info, "- Decorating Method " + method.Name);
                        }
                    }
                }

                if (decorator.DecorateProperty)
                {
                    foreach (var property in GetValidProperties(decorator, @class))
                    {
                        if (property.CustomAttributes.Add(attribute, parameterValues))
                        {
                            builder.Log(LogTypes.Info, "- Decorating Properties " + property.Name);
                        }
                    }
                }
            }
        }