diff --git a/src/.editorconfig b/src/.editorconfig
new file mode 100644
index 000000000..aaad355eb
--- /dev/null
+++ b/src/.editorconfig
@@ -0,0 +1,10 @@
+; What is EditorConfig? http://editorconfig.org/
+
+root = true
+
+; general settings
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = crlf
+insert_final_newline = false
diff --git a/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpGeneratorTests.cs b/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpGeneratorTests.cs
index 296522b2f..e61f2ad01 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpGeneratorTests.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpGeneratorTests.cs
@@ -1401,5 +1401,58 @@ public async Task When_definition_contains_datetime_converter_should_not_be_adde
Assert.DoesNotContain(@"class DateFormatConverter", code);
Assert.DoesNotContain(@"[Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter))]", code);
}
+
+ [Fact]
+ public async Task When_record_no_setter_in_class_and_constructor_provided()
+ {
+ //// Arrange
+ var schema = await JsonSchema4.FromTypeAsync
();
+ var data = schema.ToJson();
+ var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings
+ {
+ ClassStyle = CSharpClassStyle.Record
+ });
+
+ //// Act
+ var output = generator.GenerateFile("Address");
+
+ //// Assert
+ Assert.Contains (@"public string Street { get; }", output);
+ Assert.DoesNotContain(@"public string Street { get; set; }", output);
+
+ Assert.Contains("public Address(string Street, string City)", output);
+ Assert.Contains("public Address(string Street, string City)", output);
+ }
+
+ public abstract class AbstractAddress
+ {
+ [JsonProperty("city")]
+ [DefaultValue("Innsmouth")]
+ public string City { get; set; }
+
+ [JsonProperty("street")]
+ public string Street { get; set; }
+ }
+
+ [Fact]
+ public async Task When_class_is_abstract_constructor_is_protected_for_record()
+ {
+ //// Arrange
+ var schema = await JsonSchema4.FromTypeAsync();
+ var data = schema.ToJson();
+ var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings
+ {
+ ClassStyle = CSharpClassStyle.Record,
+ });
+
+ //// Act
+ var output = generator.GenerateFile("AbstractAddress");
+
+ //// Assert
+ Assert.Contains (@"public string Street { get; }", output);
+ Assert.DoesNotContain(@"public string Street { get; set; }", output);
+
+ Assert.Contains("protected AbstractAddress(string street, string city = \"Innsmouth\")", output);
+ }
}
}
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/CSharpClassStyle.cs b/src/NJsonSchema.CodeGeneration.CSharp/CSharpClassStyle.cs
index 301c43077..126362860 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/CSharpClassStyle.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp/CSharpClassStyle.cs
@@ -20,6 +20,9 @@ public enum CSharpClassStyle
Inpc,
/// Generates classes implementing the Prism base class.
- Prism
+ Prism,
+
+ /// Generates Records - read only POCOs (Plain Old C# Objects).
+ Record
}
}
\ No newline at end of file
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
index de582247b..190761132 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
@@ -70,6 +70,9 @@ public class ClassTemplateModel : ClassTemplateModelBase
/// Gets a value indicating whether the class style is Prism.
public bool RenderPrism => _settings.ClassStyle == CSharpClassStyle.Prism;
+ /// Gets a value indicating whether the class style is Record.
+ public bool RenderRecord => _settings.ClassStyle == CSharpClassStyle.Record;
+
/// Gets a value indicating whether to render ToJson() and FromJson() methods.
public bool GenerateJsonMethods => _settings.GenerateJsonMethods;
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/NJsonSchema.CodeGeneration.CSharp.csproj b/src/NJsonSchema.CodeGeneration.CSharp/NJsonSchema.CodeGeneration.CSharp.csproj
index 1d8262ddc..b6f51f456 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/NJsonSchema.CodeGeneration.CSharp.csproj
+++ b/src/NJsonSchema.CodeGeneration.CSharp/NJsonSchema.CodeGeneration.CSharp.csproj
@@ -23,6 +23,7 @@
+
@@ -31,6 +32,7 @@
+
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.Constructor.Record.liquid b/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.Constructor.Record.liquid
new file mode 100644
index 000000000..f205cd02e
--- /dev/null
+++ b/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.Constructor.Record.liquid
@@ -0,0 +1,9 @@
+{% assign skipComma = true -%}
+{% assign sortedProperties = (Properties | sort: "HasDefaultValue") -%}
+[Newtonsoft.Json.JsonConstructor]
+{% if IsAbstract %}protected{% else %}public{% endif %} {{ClassName}}({% for property in sortedProperties -%}{% if skipComma -%}{% assign skipComma = false %}{% else %}, {% endif -%} {{ property.Type }} {{ property.Name }}{% if property.HasDefaultValue == true %} = {{ property.DefaultValue }}{% endif %}{% endfor -%})
+{
+{% for property in Properties -%}
+ this.{{property.PropertyName}} = @{{property.Name}};
+{% endfor -%}
+}
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.liquid b/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.liquid
index 2c16807fe..6008eb929 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.liquid
+++ b/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.liquid
@@ -18,6 +18,10 @@
{% endif -%}
{% template Class.Constructor %}
+{% if RenderRecord == true -%}
+ {% template Class.Constructor.Record %}
+
+{% endif -%}
{% for property in Properties -%}
{% if property.HasDescription -%}
/// {{ property.Description | csharpdocs }}
@@ -42,7 +46,7 @@
[Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter))]
{% endif -%}
{% template Class.Property.Annotations %}
- public {{ property.Type }} {{ property.PropertyName }}{% if RenderInpc == false and RenderPrism == false %} { get; {% if property.HasSetter %}set; {% endif %}}{% if property.HasDefaultValue %} = {{ property.DefaultValue }};{% endif %}
+ public {{ property.Type }} {{ property.PropertyName }}{% if RenderInpc == false and RenderPrism == false %} { get; {% if property.HasSetter and RenderRecord == false %}set; {% endif %}}{% if property.HasDefaultValue %} = {{ property.DefaultValue }};{% endif %}
{% else %}
{
get { return {{ property.FieldName }}; }
diff --git a/src/NJsonSchema.CodeGeneration/NJsonSchema.CodeGeneration.csproj b/src/NJsonSchema.CodeGeneration/NJsonSchema.CodeGeneration.csproj
index a31120916..239dee27a 100644
--- a/src/NJsonSchema.CodeGeneration/NJsonSchema.CodeGeneration.csproj
+++ b/src/NJsonSchema.CodeGeneration/NJsonSchema.CodeGeneration.csproj
@@ -22,7 +22,7 @@
-
+