Giter VIP home page Giter VIP logo

fluentroslyn.csharp's Introduction

A fluent builder-pattern syntax for orchestration of domain-specific code generators.

๐Ÿ”Ž Find it on nuget.org

Cold Open (Example)

var sourceFileContents = SourceFileBuilder
    .Create($"MyDomain.Infrastructure.Queries.MyEntities")
    .Using(
        "System.Threading",
        "System.Threading.Tasks",
        "MediatR",
        "MyDomain.API.SDK.Clients.QueryResponses")
    .AddClass(handlerName, @class => @class
        .WithBase($"IRequestHandler<GetMyEntity, GetMyEntityResponse>")
        .AddField(
            "IMyEntityQueryRepository",
            field => field
                .WithAccessibility(Access.Private)
                .AsReadOnly())
        .WithConstructor(ctor => ctor
            .WithParameters(parameters => parameters
                .AddParameter("IMyEntityQueryRepository", "myEntityQueryRepository")
            )
            .WithBody(body => body
                .AddStatement("_myEntityQueryRepository = myEntityQueryRepository;")
            )
        )
        .WithMethod(
            "Handle",
            method => method
                .WithAccessibility(Access.Public)
                .WithParameters(parameters => parameters
                    .AddParameter("GetMyEntity", "query")
                    .AddParameter("CancellationToken"))
                .WithBody(body => body
                    .AddStatement("var entity = await _myEntityQueryRepository.GetAsync(query.Id);")
                    .AddStatement("return new(entity.Identity, entity.Name, entity.Description);")
                )
                .Returns("GetMyEntityResponse")
                .AsAsync()
        )
    )
    .Build();

Getting Started

โš ๏ธ WARNING

Examples last updated at version 0.1.0-alpha

Create Console Application

Create a console project in your solution, i.e. <target-project>.CodeGenerator

#!/usr/bin/env bash

# change these
repoDir="${HOME}/src/MyRepo"
targetProject="MyDomain"

# create project in solution
cd "$repoDir/project"
generatorProject = "${targetProject}.CodeGenerator"
dotnet new console --name "$generatorProject"
dotnet sln add "$generatorProject"

Create a file set generator method

example for generating query:

using StarBridge.FluentRoslyn.CSharp.Model;

namespace MyDomain.CodeGenerator;

internal class ApiGenerator
{
    private readonly IFileRepository _fileRepository;

    public ApiGenerator(IFileRepository fileRepository)
    {
        _fileRepository = fileRepository;
    }

    // example method that generates a set of files for a "query" in your api project
    internal void GenerateQuery(ProjectInfo project, Entity entity)
    {
        // response
        var response = entity.GenerateQueryResponse(project);
        _fileRepository.Save(response);

        // query
        var query = entity.GenerateQuery(project);
        _fileRepository.Save(query);

        // query handler
        var handler = entity.GenerateQueryHandler(project);
        _fileRepository.Save(handler);
    }
}

Invoke

Call it from your entry point

using StarBridge.FluentRoslyn.CSharp.Model;
using MyDomain.CodeGenerator;

var fileRepository = new FileRepository(); // out of scope for example
var apiGenerator = new ApiGenerator(fileRepository);

var projectName = new ProjectName("MyDomain");
var projectDir = "/home/username/src/MyDomain/project/MyDomain.API";
var project = new ProjectInfo(projectName, projectDir);

var entity = new Entity(
    new EntityName(
        Singular: "MyEntity",
        Plural: "TheEntities"));

apiGenerator.GenerateQuery(project, entity);

Write Generators

Example - Write each file as an extension of Entity:

using FluentRoslyn.CSharp;
using FluentRoslyn.CSharp.Model;
using Microsoft.CodeAnalysis.CSharp;

namespace MyDomain.CodeGenerator;

public static class ApiQueryFactory
{
    /// <summary>
    ///     Generates <b>MyDomain.API.SDK/Clients/QueryTheEntities/GetMyEntityResponse.cs</b>
    /// </summary>
    internal static GeneratedFile GenerateQueryResponse(this Entity entity, ProjectInfo project)
    {
        var responsePath = $"{project.SdkName}\\Clients\\QueryResponses\\Get{entity.Name.Singular}Response.cs";
        var responseFileInfo = project.GetInfo(responsePath);
        var recordName = $"Get{entity.Name.Singular}Response";
        var fileName = $"{recordName}.cs";
        var responseFileContents = SourceFileBuilder
            .Create("MyDomain.API.SDK.Clients.QueryResponses")
            .Using("MyDomain.Core.Identity")
            .AddRecord(recordName, rec => rec
                .WithParameters(param => param
                    .AddParameter(entity.Name.Identifier, "Identity")
                    .AddParameter(SyntaxKind.StringKeyword, "Name")
                    .AddParameter(SyntaxKind.StringKeyword, "Description")))
            .Build();

        var responseFile = new GeneratedFile(responseFileInfo, responseFileContents);

        return responseFile;
    }

    /// <summary>
    ///     Generates <b>MyDomain.Infrastructure.Queries/TheEntities/GetMyEntity.cs</b>
    /// </summary>
    internal static GeneratedFile GenerateQuery(this Entity entity, ProjectInfo project) { /**/ }

    /// <summary>
    ///     Generates <b>MyDomain.Infrastructure.Queries/MyEntities/GetMyEntityHandler.cs</b>
    /// </summary>
    internal static GeneratedFile GenerateQueryHandler(this Entity entity, ProjectInfo project) { /**/ }
}

Fluent Syntax - Intellisense

The fluent syntax should promote discovery ๐Ÿค” Feel free to create an issue if something isn't intuitive!

IDE Example Screenshots... Click to expand!



Backlog

  • ๐Ÿ“œ Contributing Guidelines
  • ๐Ÿงช Tests which will provide examples, and document builder permutations
  • ๐Ÿ”จ More coverage of Roslyn (Dogfooding this package for a personal project)
  • ๐Ÿช  Build Pipeline
  • ๐Ÿ’ป Command-line Interface

fluentroslyn.csharp's People

Contributors

jknightdev avatar james-arawhanui avatar jameswilliamknight avatar

Stargazers

Sigeer avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.