- {#each langs as lang}
-
{lang}
+ {#each langs as [lang, langName]}
+
{langName}
{/each}
{#if sourceCode}
{sourceCode}
diff --git a/src/main/java/io/vlingo/xoom/schemata/codegen/TypeDefinitionCompiler.java b/src/main/java/io/vlingo/xoom/schemata/codegen/TypeDefinitionCompiler.java
index 4e4891d5..21687dfb 100644
--- a/src/main/java/io/vlingo/xoom/schemata/codegen/TypeDefinitionCompiler.java
+++ b/src/main/java/io/vlingo/xoom/schemata/codegen/TypeDefinitionCompiler.java
@@ -52,6 +52,7 @@ public static TypeDefinitionCompiler compilerFor(final Stage stage, final String
*/
public static TypeDefinitionCompiler newCompilerFor(final Stage stage, final String language) {
switch (language) {
+ case "csharp":
case "java":
return forBackend(stage, new XoomCodeGenBackend(new SchemaTypeTemplateProcessingStep(), language));
default:
diff --git a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/SchemaTypeTemplateData.java b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/SchemaTypeTemplateData.java
index aa001cdf..2b38b8fc 100644
--- a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/SchemaTypeTemplateData.java
+++ b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/SchemaTypeTemplateData.java
@@ -2,7 +2,9 @@
import io.vlingo.xoom.codegen.template.TemplateData;
import io.vlingo.xoom.codegen.template.TemplateStandard;
+import io.vlingo.xoom.schemata.Schemata;
import io.vlingo.xoom.schemata.codegen.ast.types.TypeDefinition;
+import io.vlingo.xoom.schemata.codegen.template.schematype.csharp.CSharpSchemaTypeTemplateData;
import io.vlingo.xoom.schemata.codegen.template.schematype.java.JavaSchemaTypeTemplateData;
import io.vlingo.xoom.schemata.codegen.template.SchemataTemplateStandard;
@@ -19,6 +21,8 @@ private static TemplateData create(final String language, final TypeDefinition t
switch (language) {
case "java":
return JavaSchemaTypeTemplateData.from(type, version);
+ case "csharp":
+ return CSharpSchemaTypeTemplateData.from(type, version);
default:
throw new IllegalArgumentException("Unsupported language: " + language);
}
@@ -28,4 +32,19 @@ private static TemplateData create(final String language, final TypeDefinition t
public TemplateStandard standard() {
return SchemataTemplateStandard.SCHEMA_TYPE;
}
+
+ protected List
packageSegments(String reference, String category) {
+ final String[] referenceParts = reference.split(Schemata.ReferenceSeparator);
+ if (referenceParts.length < Schemata.MinReferenceParts) {
+ throw new IllegalArgumentException("Invalid fully qualified type name. Valid type names look like this :::[:].");
+ }
+ final String namespace = referenceParts[2];
+ final String className = referenceParts[3];
+
+ final String basePackage = namespace + "." + category;
+ final String localPackage = className.contains(".") ? className.substring(0, className.lastIndexOf('.')) : "";
+ return Arrays.asList((localPackage.length() > 0
+ ? basePackage + "." + localPackage
+ : basePackage).split("\\."));
+ }
}
diff --git a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateData.java b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateData.java
new file mode 100644
index 00000000..2fc88740
--- /dev/null
+++ b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateData.java
@@ -0,0 +1,207 @@
+package io.vlingo.xoom.schemata.codegen.template.schematype.csharp;
+
+import io.vlingo.xoom.codegen.template.TemplateData;
+import io.vlingo.xoom.codegen.template.TemplateParameters;
+import io.vlingo.xoom.schemata.codegen.ast.FieldDefinition;
+import io.vlingo.xoom.schemata.codegen.ast.types.BasicType;
+import io.vlingo.xoom.schemata.codegen.ast.types.ComputableType;
+import io.vlingo.xoom.schemata.codegen.ast.types.Type;
+import io.vlingo.xoom.schemata.codegen.ast.types.TypeDefinition;
+import io.vlingo.xoom.schemata.codegen.ast.values.ListValue;
+import io.vlingo.xoom.schemata.codegen.ast.values.NullValue;
+import io.vlingo.xoom.schemata.codegen.ast.values.SingleValue;
+import io.vlingo.xoom.schemata.codegen.ast.values.Value;
+import io.vlingo.xoom.schemata.codegen.template.schematype.SchemaTypeTemplateData;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.joining;
+
+public class CSharpSchemaTypeTemplateData extends SchemaTypeTemplateData {
+
+ private final TypeDefinition type;
+ private final String version;
+
+ public static TemplateData from(final TypeDefinition type, final String version) {
+ return new CSharpSchemaTypeTemplateData(type, version);
+ }
+
+ private CSharpSchemaTypeTemplateData(final TypeDefinition type, final String version) {
+ this.type = type;
+ this.version = version;
+ }
+
+ @Override
+ public TemplateParameters parameters() {
+ List properties = properties();
+ return TemplateParameters
+ .with(CSharpSchemaTypeTemplateParameter.NAMESPACE, namespace())
+ .and(CSharpSchemaTypeTemplateParameter.IMPORTS, imports())
+ .and(CSharpSchemaTypeTemplateParameter.TYPE_NAME, typeName())
+ .and(CSharpSchemaTypeTemplateParameter.BASE_TYPE_NAME, baseTypeName())
+ .and(CSharpSchemaTypeTemplateParameter.PROPERTIES, properties)
+ .and(CSharpSchemaTypeTemplateParameter.NEEDS_CONSTRUCTOR, needsConstructor(properties))
+ .and(CSharpSchemaTypeTemplateParameter.NEEDS_DEFAULT_CONSTRUCTOR, needsDefaultConstructor(properties));
+ }
+
+ private String namespace() {
+ return packageSegments(type.fullyQualifiedTypeName, type.category.name()+"s")
+ .stream()
+ .map(p -> p.substring(0, 1).toUpperCase() + p.substring(1))
+ .collect(joining("."));
+ }
+
+ private List imports() {
+ List properties = properties();
+ return Stream.of("System", "Vlingo.Lattice.Model", "Vlingo.Xoom.Common.Version")
+ .filter(i -> !i.equals("System") || properties.stream().anyMatch(p -> p.constructorInitializer.startsWith("DateTimeOffset.")))
+ .filter(i -> !i.equals("Vlingo.Xoom.Common.Version") || properties.stream().anyMatch(p -> p.constructorInitializer.startsWith("SemanticVersion.")))
+ .collect(Collectors.toList());
+ }
+
+ private String typeName() {
+ return type.typeName;
+ }
+
+ private String baseTypeName() {
+ return "DomainEvent";
+ }
+
+ private List properties() {
+ return type.children.stream()
+ .filter(c -> c instanceof FieldDefinition)
+ .map(c -> (FieldDefinition) c)
+ .map(this::toProperty)
+ .collect(Collectors.toList());
+ }
+
+ private boolean needsConstructor(final List properties) {
+ return properties.stream().anyMatch(f -> !f.isComputed);
+ }
+
+ private boolean needsDefaultConstructor(final List properties) {
+ return properties.size() != 0 && properties.stream().allMatch(f -> f.isComputed || f.defaultValue != null);
+ }
+
+ private String initializationOf(final FieldDefinition field, final TypeDefinition owner) {
+ Type type = field.type;
+ if (type instanceof ComputableType) {
+ switch (((ComputableType) type).typeName) {
+ case "type":
+ return String.format("\"%s\"", owner.typeName);
+ case "version":
+ return String.format("SemanticVersion.toValue(\"%s\")", this.version);
+ case "timestamp":
+ return "DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()";
+ }
+ }
+ return field.name;
+ }
+
+ private String type(final Type type) {
+ if (type instanceof BasicType) {
+ return primitive((BasicType) type);
+ } else if (type instanceof ComputableType) {
+ return computable((ComputableType) type);
+ }
+ return type.name();
+ }
+
+ private String primitive(final BasicType basicType) {
+ String result;
+ switch (basicType.typeName) {
+ case "boolean":
+ result = "bool";
+ break;
+ case "byte":
+ case "char":
+ case "short":
+ case "int":
+ case "long":
+ case "float":
+ case "double":
+ case "string":
+ result = basicType.typeName;
+ break;
+ default:
+ result = "object";
+ break;
+ }
+
+ return basicType.isArrayType() ? result + "[]" : result;
+ }
+
+ private String computable(final ComputableType computableType) {
+ switch (computableType.typeName) {
+ case "type":
+ return "string";
+ case "timestamp":
+ return "long";
+ case "version":
+ return "int";
+ default:
+ return "object";
+ }
+ }
+
+ private String cSharpLiteralOf(FieldDefinition field) {
+ Value> value = field.defaultValue.orElseGet(NullValue::new);
+
+ if(value instanceof NullValue) {
+ return null;
+ }
+
+ if(value instanceof SingleValue) {
+ return cSharpLiteralOf((SingleValue>) value);
+ }
+
+ if(value instanceof ListValue) {
+ return cSharpLiteralOf((ListValue>) value);
+ }
+
+ throw new IllegalStateException("Unsupported value type encountered");
+ }
+
+ private String cSharpLiteralOf(final SingleValue> value) {
+ return value.value().toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ private String cSharpLiteralOf(final ListValue value) {
+ return value.value().stream()
+ .map(e -> ((SingleValue>) e).value())
+ .collect(joining(", ", "{ ", " }"))
+ .toString();
+ }
+
+ private Property toProperty(final FieldDefinition field) {
+ return new Property(
+ type(field.type),
+ field.name.substring(0, 1).toUpperCase() + field.name.substring(1),
+ field.name,
+ cSharpLiteralOf(field),
+ initializationOf(field, type),
+ field.type instanceof ComputableType
+ );
+ }
+
+ public static class Property {
+ public final String type;
+ public final String name;
+ public final String argumentName;
+ public final String defaultValue;
+ public final String constructorInitializer;
+ public final boolean isComputed;
+
+ public Property(final String type, final String name, final String argumentName, final String defaultValue, final String constructorInitializer, final boolean isComputed) {
+ this.type = type;
+ this.name = name;
+ this.argumentName = argumentName;
+ this.defaultValue = defaultValue;
+ this.constructorInitializer = constructorInitializer;
+ this.isComputed = isComputed;
+ }
+ }
+}
diff --git a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateParameter.java b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateParameter.java
new file mode 100644
index 00000000..e4e85671
--- /dev/null
+++ b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/csharp/CSharpSchemaTypeTemplateParameter.java
@@ -0,0 +1,23 @@
+package io.vlingo.xoom.schemata.codegen.template.schematype.csharp;
+
+import io.vlingo.xoom.codegen.template.ParameterKey;
+
+public enum CSharpSchemaTypeTemplateParameter implements ParameterKey {
+ NAMESPACE("namespace"),
+ TYPE_NAME("typeName"),
+ BASE_TYPE_NAME("baseTypeName"),
+ IMPORTS("imports"),
+ PROPERTIES("properties"),
+ NEEDS_CONSTRUCTOR("needsConstructor"),
+ NEEDS_DEFAULT_CONSTRUCTOR("needsDefaultConstructor");
+
+ public final String key;
+
+ private CSharpSchemaTypeTemplateParameter(final String key) {
+ this.key = key;
+ }
+
+ public String value() {
+ return this.key;
+ }
+ }
diff --git a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/java/JavaSchemaTypeTemplateData.java b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/java/JavaSchemaTypeTemplateData.java
index a07982d1..62f9b90d 100644
--- a/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/java/JavaSchemaTypeTemplateData.java
+++ b/src/main/java/io/vlingo/xoom/schemata/codegen/template/schematype/java/JavaSchemaTypeTemplateData.java
@@ -3,7 +3,6 @@
import io.vlingo.xoom.codegen.template.TemplateData;
import io.vlingo.xoom.codegen.template.TemplateParameters;
import io.vlingo.xoom.lattice.model.DomainEvent;
-import io.vlingo.xoom.schemata.Schemata;
import io.vlingo.xoom.schemata.codegen.ast.FieldDefinition;
import io.vlingo.xoom.schemata.codegen.ast.types.BasicType;
import io.vlingo.xoom.schemata.codegen.ast.types.ComputableType;
@@ -63,20 +62,7 @@ private List computedFields(final List fields) {
}
private String packageName() {
- final String category = type.category.name().toLowerCase();
- final String reference = type.fullyQualifiedTypeName;
- final String[] referenceParts = reference.split(Schemata.ReferenceSeparator);
- if (referenceParts.length < Schemata.MinReferenceParts) {
- throw new IllegalArgumentException("Invalid fully qualified type name. Valid type names look like this :::[:].");
- }
- final String namespace = referenceParts[2];
- final String className = referenceParts[3];
-
- final String basePackage = namespace + "." + category;
- final String localPackage = className.contains(".") ? className.substring(0, className.lastIndexOf('.')) : "";
- return localPackage.length() > 0
- ? basePackage + "." + localPackage
- : basePackage;
+ return packageSegments(type.fullyQualifiedTypeName, type.category.name().toLowerCase()).stream().collect(joining("."));
}
private String typeName() {
diff --git a/src/main/resources/codegen/c_sharp/SchemaType.ftl b/src/main/resources/codegen/c_sharp/SchemaType.ftl
new file mode 100644
index 00000000..5d62f522
--- /dev/null
+++ b/src/main/resources/codegen/c_sharp/SchemaType.ftl
@@ -0,0 +1,31 @@
+<#list imports as import>
+using ${import};
+#list>
+
+namespace ${namespace}
+{
+ public sealed class ${typeName} : ${baseTypeName}
+ {
+ <#list properties as property>
+ public ${property.type} ${property.name} { get; }<#if property.defaultValue??> = ${property.defaultValue};#if>
+
+ #list>
+ <#if needsConstructor>
+ public ${typeName}(<#list properties?filter(f -> !f.isComputed) as property>${property.type} ${property.argumentName}<#sep>, #list>) {
+ <#list properties as property>
+ ${property.name} = ${property.constructorInitializer};
+ #list>
+ }
+ #if>
+ <#if needsDefaultConstructor>
+ <#if needsConstructor>
+
+ #if>
+ public ${typeName}() {
+ <#list properties?filter(f -> f.isComputed) as property>
+ ${property.name} = ${property.constructorInitializer};
+ #list>
+ }
+ #if>
+ }
+}
diff --git a/src/test/java/io/vlingo/xoom/schemata/codegen/specs/CSharpCodeGenTests.java b/src/test/java/io/vlingo/xoom/schemata/codegen/specs/CSharpCodeGenTests.java
index 5496c4bb..30b56e57 100644
--- a/src/test/java/io/vlingo/xoom/schemata/codegen/specs/CSharpCodeGenTests.java
+++ b/src/test/java/io/vlingo/xoom/schemata/codegen/specs/CSharpCodeGenTests.java
@@ -9,9 +9,7 @@
import io.vlingo.xoom.codegen.TextExpectation;
import io.vlingo.xoom.schemata.codegen.TypeDefinitionCompilerActor;
-import org.junit.Ignore;
-@Ignore
public class CSharpCodeGenTests extends CodeGenSpecs {
@Override
protected TypeDefinitionCompilerActor compiler() {
diff --git a/src/test/resources/text-expectations/c_sharp/all-single-types.text b/src/test/resources/text-expectations/c_sharp/all-single-types.text
new file mode 100644
index 00000000..bed6014a
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/all-single-types.text
@@ -0,0 +1,48 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string EventType { get; }
+
+ public long OccurredOn { get; }
+
+ public int EventVersion { get; }
+
+ public bool BooleanAttribute { get; }
+
+ public byte ByteAttribute { get; }
+
+ public char CharAttribute { get; }
+
+ public double DoubleAttribute { get; }
+
+ public float FloatAttribute { get; }
+
+ public int IntAttribute { get; }
+
+ public long LongAttribute { get; }
+
+ public short ShortAttribute { get; }
+
+ public string StringAttribute { get; }
+
+ public SalutationHappened(bool booleanAttribute, byte byteAttribute, char charAttribute, double doubleAttribute, float floatAttribute, int intAttribute, long longAttribute, short shortAttribute, string stringAttribute) {
+ EventType = "SalutationHappened";
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ EventVersion = SemanticVersion.toValue("0.0.1");
+ BooleanAttribute = booleanAttribute;
+ ByteAttribute = byteAttribute;
+ CharAttribute = charAttribute;
+ DoubleAttribute = doubleAttribute;
+ FloatAttribute = floatAttribute;
+ IntAttribute = intAttribute;
+ LongAttribute = longAttribute;
+ ShortAttribute = shortAttribute;
+ StringAttribute = stringAttribute;
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/basic-arrays-with-default-values.text b/src/test/resources/text-expectations/c_sharp/basic-arrays-with-default-values.text
new file mode 100644
index 00000000..96b6bd5a
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/basic-arrays-with-default-values.text
@@ -0,0 +1,40 @@
+using Vlingo.Lattice.Model;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public bool[] BooleanAttribute { get; } = { true, false, true };
+
+ public byte[] ByteAttribute { get; } = { 4, 3, 2, 1 };
+
+ public char[] CharAttribute { get; } = { 'x', 'y', 'z' };
+
+ public double[] DoubleAttribute { get; } = { 0.23, 0.22, 0.21 };
+
+ public float[] FloatAttribute { get; } = { 0.42f, 0.42f, 0.1f };
+
+ public int[] IntAttribute { get; } = { 4242, 424242, 42424242 };
+
+ public long[] LongAttribute { get; } = { 42L, 4242L, 424242L };
+
+ public short[] ShortAttribute { get; } = { 258, 259, 260 };
+
+ public string[] StringAttribute { get; } = { "foo", "bar", "baz" };
+
+ public SalutationHappened(bool[] booleanAttribute, byte[] byteAttribute, char[] charAttribute, double[] doubleAttribute, float[] floatAttribute, int[] intAttribute, long[] longAttribute, short[] shortAttribute, string[] stringAttribute) {
+ BooleanAttribute = booleanAttribute;
+ ByteAttribute = byteAttribute;
+ CharAttribute = charAttribute;
+ DoubleAttribute = doubleAttribute;
+ FloatAttribute = floatAttribute;
+ IntAttribute = intAttribute;
+ LongAttribute = longAttribute;
+ ShortAttribute = shortAttribute;
+ StringAttribute = stringAttribute;
+ }
+
+ public SalutationHappened() {
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/basic-arrays.text b/src/test/resources/text-expectations/c_sharp/basic-arrays.text
new file mode 100644
index 00000000..277e893a
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/basic-arrays.text
@@ -0,0 +1,37 @@
+using Vlingo.Lattice.Model;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public bool[] BooleanAttribute { get; }
+
+ public byte[] ByteAttribute { get; }
+
+ public char[] CharAttribute { get; }
+
+ public double[] DoubleAttribute { get; }
+
+ public float[] FloatAttribute { get; }
+
+ public int[] IntAttribute { get; }
+
+ public long[] LongAttribute { get; }
+
+ public short[] ShortAttribute { get; }
+
+ public string[] StringAttribute { get; }
+
+ public SalutationHappened(bool[] booleanAttribute, byte[] byteAttribute, char[] charAttribute, double[] doubleAttribute, float[] floatAttribute, int[] intAttribute, long[] longAttribute, short[] shortAttribute, string[] stringAttribute) {
+ BooleanAttribute = booleanAttribute;
+ ByteAttribute = byteAttribute;
+ CharAttribute = charAttribute;
+ DoubleAttribute = doubleAttribute;
+ FloatAttribute = floatAttribute;
+ IntAttribute = intAttribute;
+ LongAttribute = longAttribute;
+ ShortAttribute = shortAttribute;
+ StringAttribute = stringAttribute;
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/basic-with-default-values.text b/src/test/resources/text-expectations/c_sharp/basic-with-default-values.text
new file mode 100644
index 00000000..3d436490
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/basic-with-default-values.text
@@ -0,0 +1,54 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string EventType { get; }
+
+ public long OccurredOn { get; }
+
+ public int EventVersion { get; }
+
+ public bool BooleanAttribute { get; } = true;
+
+ public byte ByteAttribute { get; } = 4;
+
+ public char CharAttribute { get; } = 'x';
+
+ public double DoubleAttribute { get; } = 0.23;
+
+ public float FloatAttribute { get; } = 0.42f;
+
+ public int IntAttribute { get; } = 4242;
+
+ public long LongAttribute { get; } = 42L;
+
+ public short ShortAttribute { get; } = 258;
+
+ public string StringAttribute { get; } = "foo";
+
+ public SalutationHappened(bool booleanAttribute, byte byteAttribute, char charAttribute, double doubleAttribute, float floatAttribute, int intAttribute, long longAttribute, short shortAttribute, string stringAttribute) {
+ EventType = "SalutationHappened";
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ EventVersion = SemanticVersion.toValue("0.0.1");
+ BooleanAttribute = booleanAttribute;
+ ByteAttribute = byteAttribute;
+ CharAttribute = charAttribute;
+ DoubleAttribute = doubleAttribute;
+ FloatAttribute = floatAttribute;
+ IntAttribute = intAttribute;
+ LongAttribute = longAttribute;
+ ShortAttribute = shortAttribute;
+ StringAttribute = stringAttribute;
+ }
+
+ public SalutationHappened() {
+ EventType = "SalutationHappened";
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ EventVersion = SemanticVersion.toValue("0.0.1");
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/basic-with-package.text b/src/test/resources/text-expectations/c_sharp/basic-with-package.text
new file mode 100644
index 00000000..2f0a6191
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/basic-with-package.text
@@ -0,0 +1,27 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Io.Vlingo.Xoom.Mynamespace.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string EventType { get; }
+
+ public long OccurredOn { get; }
+
+ public int EventVersion { get; }
+
+ public string ToWhom { get; }
+
+ public string Text { get; }
+
+ public SalutationHappened(string toWhom, string text) {
+ EventType = "SalutationHappened";
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ EventVersion = SemanticVersion.toValue("0.0.1");
+ ToWhom = toWhom;
+ Text = text;
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/basic.text b/src/test/resources/text-expectations/c_sharp/basic.text
new file mode 100644
index 00000000..8911d944
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/basic.text
@@ -0,0 +1,27 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string EventType { get; }
+
+ public long OccurredOn { get; }
+
+ public int EventVersion { get; }
+
+ public string ToWhom { get; }
+
+ public string Text { get; }
+
+ public SalutationHappened(string toWhom, string text) {
+ EventType = "SalutationHappened";
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ EventVersion = SemanticVersion.toValue("0.0.1");
+ ToWhom = toWhom;
+ Text = text;
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/computed-only.text b/src/test/resources/text-expectations/c_sharp/computed-only.text
new file mode 100644
index 00000000..31e73f8b
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/computed-only.text
@@ -0,0 +1,21 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string Name { get; }
+
+ public long PublishedOn { get; }
+
+ public int PublishedVersion { get; }
+
+ public SalutationHappened() {
+ Name = "SalutationHappened";
+ PublishedOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ PublishedVersion = SemanticVersion.toValue("0.0.1");
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/minimal.text b/src/test/resources/text-expectations/c_sharp/minimal.text
new file mode 100644
index 00000000..20a54e89
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/minimal.text
@@ -0,0 +1,13 @@
+using Vlingo.Lattice.Model;
+
+namespace Context.Events
+{
+ public sealed class SalutationHappened : DomainEvent
+ {
+ public string EventType { get; }
+
+ public SalutationHappened() {
+ EventType = "SalutationHappened";
+ }
+ }
+}
diff --git a/src/test/resources/text-expectations/c_sharp/price-changed.text b/src/test/resources/text-expectations/c_sharp/price-changed.text
new file mode 100644
index 00000000..9e967377
--- /dev/null
+++ b/src/test/resources/text-expectations/c_sharp/price-changed.text
@@ -0,0 +1,24 @@
+using System;
+using Vlingo.Lattice.Model;
+using Vlingo.Xoom.Common.Version;
+
+namespace Context.Events
+{
+ public sealed class PriceChanged : DomainEvent
+ {
+ public int EventVersion { get; }
+
+ public long OccurredOn { get; }
+
+ public Price OldPrice { get; }
+
+ public Price NewPrice { get; }
+
+ public PriceChanged(Price oldPrice, Price newPrice) {
+ EventVersion = SemanticVersion.toValue("0.5.1");
+ OccurredOn = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ OldPrice = oldPrice;
+ NewPrice = newPrice;
+ }
+ }
+}