Exemplo n.º 1
0
        public Job Generate(TypeStore typeStore, Func <ITypeDefinition, bool> includeType = default, Func <IMethod, bool> includeMethod = default, string templateStyles = default, TemplateExportStyle embedTemplatesExport = TemplateExportStyle.File)
        {
            //
            const string voidTypeName        = "System.Void";
            const string enumerableTypeName  = "System.Collections.IEnumerable";
            const string genericListTypeName = "System.Collections.Generic.IList";
            const string equatableTypeName   = "System.IEquatable";

            includeType ??= _ => true;
            includeMethod ??= _ => true;

            var typesToProcess = new List <TypeToProcess>();

            // Iterate through the public types
            foreach (var type in typeStore.GetTypes().Where(t => t.Accessibility == Accessibility.Public && // only pull in public items
                                                            t.Kind == TypeKind.Class &&                     // which are classes
                                                            !t.IsStatic &&                                  // and aren't static
                                                            t.TypeParameters.Count == 0 &&                  // and aren't generics
                                                            includeType(t)))                                // and matches with custom additional properties
            {
                // now pull in those public properties for which there is a getter AND a setter and it isn't static
                var properties = type.Properties.Where(property => property.Accessibility == Accessibility.Public && property.CanGet && property.CanSet && !property.IsStatic &&
                                                       property.DeclaringType.Equals(type)).
                                 Select(property =>
                {
                    var propertyType = property.ReturnType;

                    var baseTypes    = propertyType.GetAllBaseTypeDefinitions();
                    var isCollection = baseTypes.Any(bt => bt.FullName == genericListTypeName) || propertyType.ReflectionName == enumerableTypeName;

                    var notes = new StringBuilder();

                    if (isCollection)
                    {
                        notes.AppendLine($"Collection.");
                    }

                    // if this is a reference type, lets check to see if we have an IEquatable implementation
                    if ((property.ReturnType.IsReferenceType ?? false) && !baseTypes.Any(bt => bt.FullName == equatableTypeName))
                    {
                        notes.Append($"{property.ReturnType.FullName} doesn't have an implementation of IEquatable, use a field or a static to hold its value to reduce updates.");
                    }

                    var prop = new Property()
                    {
                        Source = property.Name
                    };

                    if (notes.Length > 0)
                    {
                        prop.Notes = notes.ToString();
                    }

                    return(prop);
                }
                                        ).ToList();

                // get those public void methods which aren't constructors, destructors, aren't static, aren't operations and aren't generic and have less than 5 parameters
                var methods = type.Methods
                              .Where(method =>
                                     !method.IsConstructor && !method.IsDestructor && method.HasBody && !method.IsStatic && !method.IsOperator && method.TypeParameters.Count == 0 &&
                                     method.Accessibility == Accessibility.Public && method.ReturnType.FullName == voidTypeName && method.DeclaringType.Equals(type) && includeMethod(method)).
                              Select(method => method.Name).
                              Distinct().
                              Select(methodName => new Method()
                {
                    Source = methodName
                }).
                              OrderBy(m => m.Source).
                              ToList();

                // and finally, those public events which aren't static.
                var events = type.Events.Where(e => e.Accessibility == Accessibility.Public && !e.IsStatic && e.DeclaringType.Equals(type)).Select(e => new Event()
                {
                    Source = e.Name
                }).ToList();

                var typeToProcess = new TypeToProcess(type.FullName, new Style()
                {
                    MethodName = type.Name
                }, properties, methods, events);

                typesToProcess.Add(typeToProcess);
            }

            // if template style specified, load up the templates
            var templates = string.IsNullOrEmpty(templateStyles) ? new List <Template> (): ResourceTemplateLoader.ReadFor(templateStyles);

            var generation = new Configuration("Enter your namespace here", RootTemplateName, templates
                                               , Style.Type,
                                               new List <CodeOutputType>()
            {
                CodeOutputType.Create <Styles.Extension.ModelFactory>(Styles.Extension.Style.Type)
            });

            var generatedRoot = new Job(typesToProcess, generation);

            return(generatedRoot);
        }
Exemplo n.º 2
0
        /// <summary>
        /// User has requested the generation of a specification file for an assembly.
        /// </summary>
        /// <param name="assembly"></param>
        /// <param name="outputPath"></param>
        /// <param name="typeFilter"></param>
        /// <param name="methodFilter"></param>
        /// <param name="templatesStyle"></param>
        /// <param name="templateExportStyle"></param>
        public static void GenerateSpecification(FileInfo assembly, string outputPath = default,
                                                 string typeFilter = default, string methodFilter = default, string templatesStyle = default,
                                                 TemplateExportStyle templateExportStyle = TemplateExportStyle.Embed)
        {
            var typeStore = new TypeStore();

            typeStore.Load(Path.Join(assembly.DirectoryName, assembly.Name));

            var g = new global::Birch.Generator.Specification.Generator(Path.Join(Directory.GetCurrentDirectory(), "\\Templates"));

            Func <ITypeDefinition, bool> typeFilterFunc;

            // lets see if we can convert the type filter into something that can be used at runtime...

            if (!string.IsNullOrEmpty(typeFilter))
            {
                try
                {
                    var parameter = System.Linq.Expressions.Expression.Parameter(typeof(ITypeDefinition), "typeDefinition");

                    var expression = DynamicExpressionParser.ParseLambda(new[] { parameter }, null, typeFilter);

                    var compiled = expression.Compile();

                    typeFilterFunc = (typeDefinition) => (bool)compiled.DynamicInvoke(typeDefinition);
                }
                catch (Exception exception)
                {
                    throw new ArgumentException($"Unable to parse type filter:'{typeFilter}'", exception);
                }
            }
            else
            {
                // just pull in everything
                typeFilterFunc = (s) => true;
            }

            Func <IMethod, bool> methodFilterFunc;

            if (!string.IsNullOrEmpty(methodFilter))
            {
                try
                {
                    var parameter = System.Linq.Expressions.Expression.Parameter(typeof(IMethod), "method");

                    var expression = DynamicExpressionParser.ParseLambda(new[] { parameter }, null, methodFilter);

                    var compiled = expression.Compile();

                    methodFilterFunc = (typeDefinition) => (bool)compiled.DynamicInvoke(typeDefinition);
                }
                catch (Exception exception)
                {
                    throw new ArgumentException($"Unable to method filter:'{methodFilter}'", exception);
                }
            }
            else
            {
                // just pull in everything
                methodFilterFunc = (s) => true;
            }


            var r = g.Generate(typeStore, typeFilterFunc, methodFilterFunc, templatesStyle);

            // if the user specified they want their templates to be individually saved, then we need to do that as well...
            if (templateExportStyle == TemplateExportStyle.File)
            {
                var outputDirectory = Path.GetDirectoryName(outputPath);

                var revisedTemplates = new List <Template>();

                foreach (var template in r.Configuration.Templates)
                {
                    var fileName = $"{template.Name}.{TemplateExtension}";

                    var fullPath = Path.Join(outputDirectory, fileName);

                    File.WriteAllText(fullPath, template.Content);

                    revisedTemplates.Add(new Template(template.Name, template.Type, TemplateLocation.File)
                    {
                        Path = fileName
                    });
                }

                r.Configuration.Templates = revisedTemplates;
            }

            var f      = new JsonFormatter();
            var output = f.Format(r);

            if (outputPath != null)
            {
                File.WriteAllText(outputPath, output);
                Console.WriteLine(Resources.SpecificationFileWritten, outputPath);
            }
            else
            {
                Console.WriteLine(output);
            }
        }