This is a small .NET library that enables easy C# code generation based on Classes and its elements.
It has ability to create ClassModels
and write it to .cs files.
Can specify their Members (Constructor
, Field
, Property
, Method
) including Attributes
and Parameters
.
Defining namespace
and using
Directives is supported as well.
Library can also generate Enums
and Interfaces
, and create NestedClasses
inside parent class.
BaseElement has Config for: IndentSize, Comment, CommentHasSummaryTag(df:true), AccessModifier, BuiltInDataType, CustomDataType, Name
Property more Config: IsGetOnly, IsAutoImplemented, GetterBody, SetterBody
CsGenerator Settings are: DefaultTabSize
: 4 | OutputDirectory
: "Output" |
-- List of components --
AccessModifier: public, private, protected, pnternal, protected_internal
BuiltInDataType: void, bool, byte, int, long, decimal, float, double, char, string, object
CommonDataType: DateTime, Guid
KeyWord: this, abstract, partial, static, new, virtual, override, sealed, const, async, readOnly
IndentType: None, Single, Double, Triple, Quadruple
For more complex code with indented IF segments specific Indent value should be set (in a loop) for all internal elements.
Package targets .NET Standard 2.0 so can be used both with .NetFramework and .NetCore / .Net (new unified)
Installation package: 'Install-Package CsCodeGenerator'
If you find this project useful you can mark it by leaving a Github *Star.
Please read CONTRIBUTING for details on code of conduct, and the process for submitting pull requests.
Want to Contact us for Development & Consulting: www.codis.tech
Also take a look into others packages:
-Open source (MIT or cFOSS) authored .Net libraries (@Infopedia.io personal blog post)
№ | .Net library | Description |
---|---|---|
1 | EFCore.BulkExtensions | EF Core Bulk CRUD Ops (Flagship Lib) |
2 | EFCore.UtilExtensions | EF Core Custom Annotations and AuditInfo |
3 | EFCore.FluentApiToAnnotation | Converting FluentApi configuration to Annotations |
4 | FixedWidthParserWriter | Reading & Writing fixed-width/flat data files |
5 | CsCodeGenerator | C# code generation based on Classes and elements |
6 | CsCodeExample | Examples of C# code in form of a simple tutorial |
Class Inheritance Hierarchy
|-* BaseElement
ClassModel : -----|
Property : -- Field : ----------|
Constructor : Method : ---------|
EnumModel : ------|
InterfaceModel : -|
Component Composition
CsGenerator
|
|---Files
|
|---Enums
|
|---Classes
|
|---Fields
|
|---Constructors (DefaultConstructor first)
| |---Attributes
| | |--- Parameters
| |
| |---Parameters
|
|---Properties
| |---Attributes
| | |--- Parameters
| |
| |---Parameters
|
|---Methods
| |---Attributes
| | |--- Parameters
| |
| |---Parameters
|
|---NestedClasses (recursively)
|--- ...
Following is first example of ComplexNumber class and then creating its ClassModel for writing to Complex.cs
Class we want to generate:
using System;
using System.Model;
namespace CsCodeGenerator.Tests
{
[Description("Some class info")]
public partial class ComplexNumber : SomeBaseClass, NumbericInterface
{
protected const double PI = 3.14;
private string remark;
public ComplexNumber() { }
public ComplexNumber(double real, double imaginary = 0)
{
Real = real;
Imaginary = imaginary;
}
public static string DefaultFormat { get; } = "a + b * i";
public double Real { get; set; }
public double Imaginary { get; set; }
public virtual string Remark
{
get { return remark; }
set { remark = value; }
}
public double Modul()
{
return Math.Sqrt(Real * Real + Imaginary * Imaginary);
}
public ComplexNumber Add(ComplexNumber input)
{
ComplexNumber result = new ComplexNumber();
result.Real = Real + input.Real;
result.Imaginary = Imaginary + input.Imaginary;
return result;
}
/// <summary>
// example of 2 KeyWords(new and virtual), usually here would be just virtual
/// <summary>
public new virtual string ToString()
{
return $"({Real:0.00}, {Imaginary:0.00})";
}
}
}
Code to do it:
var usingDirectives = new List<string>
{
"using System;",
"using System.ComponentModel;"
};
string fileNameSpace = $"{Util.Namespace} CsCodeGenerator.Tests";
string complexNumberText = "ComplexNumber";
ClassModel complexNumberClass = new ClassModel(complexNumberText);
complexNumberClass.SingleKeyWord = KeyWord.Partial; //or: complexNumberClass.KeyWords.Add(KeyWord.Partial);
complexNumberClass.BaseClass = "SomeBaseClass";
complexNumberClass.Interfaces.Add("NumbericInterface)";
var descriptionAttribute = new AttributeModel("Description")
{
SingleParameter = new Parameter(@"""Some class info""")
};
complexNumberClass.AddAttribute(descriptionAttribute);
complexNumberClass.DefaultConstructor.IsVisible = true;
Constructor secondConstructor = new Constructor(complexNumberClass.Name);
secondConstructor.Parameters.Add(new Parameter(BuiltInDataType.Double, "real"));
secondConstructor.Parameters.Add(new Parameter(BuiltInDataType.Double, "imaginary") { Value = "0" });
secondConstructor.BodyLines.Add("Real = real;");
secondConstructor.BodyLines.Add("Imaginary = imaginary;");
complexNumberClass.Constructors.Add(secondConstructor);
var fields = new Field[]
{
new Field(BuiltInDataType.Double, "PI") { SingleKeyWord = KeyWord.Const, DefaultValue = "3.14" },
new Field(BuiltInDataType.String, "remark") { AccessModifier = AccessModifier.Private },
}.ToDictionary(a => a.Name, a => a);
var properties = new Property[]
{
new Property(BuiltInDataType.String, "DefaultFormat")
{
SingleKeyWord = KeyWord.Static,
IsGetOnly = true,
DefaultValue = @"""a + b * i"""
},
new Property(BuiltInDataType.Double, "Real"),
new Property(BuiltInDataType.Double, "Imaginary"),
new Property(BuiltInDataType.String, "Remark")
{
SingleKeyWord = KeyWord.Virtual,
IsAutoImplemented = false,
GetterBody = "remark",
SetterBody = "remark = value"
},
}.ToDictionary(a => a.Name, a => a);
var methods = new Method[]
{
new Method(BuiltInDataType.Double, "Modul")
{
BodyLines = new List<string> { "return Math.Sqrt(Real * Real + Imaginary * Imaginary);" }
},
new Method(complexNumberText, "Add")
{
Parameters = new List<Parameter> { new Parameter("ComplexNumber", "input") },
BodyLines = new List<string>
{
"ComplexNumber result = new ComplexNumber();",
"result.Real = Real + input.Real;",
"result.Imaginary = Imaginary + input.Imaginary;",
"return result;"
}
},
new Method(BuiltInDataType.String, "ToString")
{
Comment = "example of 2 KeyWords(new and virtual), usually here would be just virtual",
KeyWords = new List<KeyWord> { KeyWord.New, KeyWord.Virtual },
BodyLines = new List<string> { "return $\"({Real:0.00}, {Imaginary:0.00})\";" }
}
}.ToDictionary(a => a.Name, a => a);
complexNumberClass.Fields = fields;
complexNumberClass.Properties = properties;
complexNumberClass.Methods = methods;
FileModel complexNumberFile = new FileModel(complexNumberText);
complexNumberFile.LoadUsingDirectives(usingDirectives);
complexNumberFile.Namespace = fileNameSpace;
complexNumberFile.Classes.Add(complexNumberClass.Name, complexNumberClass);
CsGenerator csGenerator = new CsGenerator();
csGenerator.Files.Add(complexNumberFile.Name, complexNumberFile);
csGenerator.CreateFiles(); //Console.Write(complexNumberFile);