private void _generateChoice(CSharpEmitter emitter, string typeName, string fieldName, ChoiceDefinition def, bool root = false)
{
typeName = _getDefinitionName(typeName, fieldName, def);
if (!root)
{
_generateChoiceTags(emitter, def);
emitter.WriteLine();
}
using(var cls = emitter.Class(typeName, true))
{
cls.AbstractProperty("Tag", "Tags", Access.Public);
foreach(var field in def.Fields)
{
var tag = _transformFieldName(field.Name);
var optionTypeName = _choiceOptionNeedsWrapper(field)
? _transformFieldName(field.Name) + "Wrapper"
: _getDefinitionName(null, field.Name, field.Type);
var valueTypeName = _getDefinitionName(null, field.Name, field.Type);
cls.WriteLine();
cls.Property("Is" + tag, "bool", "return this.Tag == Tags." + tag + ";");
cls.WriteLine();
cls.Property("As" + tag, valueTypeName,
_choiceOptionNeedsWrapper(field)
? "return ((" + optionTypeName + ")this).Item;"
: "return (" + optionTypeName + ")this;");
cls.WriteLine();
Parameter[] parameters = _getChoiceOptionForwardedParameters(field);
using(var method = cls.StaticMethod("New" + tag, typeName, parameters))
{
var paramsArr = parameters.Select(p => p.Name).ToArray();
var paramsStr = string.Join(", ", paramsArr);
method.WriteLine("return new " + optionTypeName + "(" + paramsStr + ");");
}
}
cls.WriteLine();
var schemaStr = "new ChoiceSchema(false, " + Environment.NewLine
+ string.Join("," + Environment.NewLine,
def.Fields.Select(f => cls.IndentString(1) + "new FieldSchema(\"" + _transformFieldName(f.Name) + "\", " + f.Tag
+ ", Value<" + _getDefinitionName(null, f.Name, f.Type) + ">.Schema)").ToArray())
+ ")";
cls.StaticReadonlyField("Schema", "ISchema", schemaStr);
cls.WriteLine();
using (var load = cls.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") }))
{
load.WriteLine("{0} ret = null;", typeName);
load.WriteLine("Tags tag = (Tags)stream.EnterChoice();");
using (var sw = load.Switch("tag"))
{
foreach(var field in def.Fields)
{
var tag = _transformFieldName(field.Name);
var optionTypeName = _choiceOptionNeedsWrapper(field)
? _transformFieldName(field.Name) + "Wrapper"
: _getDefinitionName(null, field.Name, field.Type);
sw.Case("Tags." + tag);
sw.WriteLine("ret = Value<{0}>.Load(stream);", optionTypeName);
sw.Break();
}
sw.Default();
sw.WriteLine("throw new Exception();");
sw.Indent--;
}
load.WriteLine("stream.LeaveChoice();");
load.WriteLine("return ret;");
}
cls.WriteLine();
using (var save = cls.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") }))
{
save.WriteLine("sink.EnterChoice((byte)value.Tag);");
using (var sw = save.Switch("value.Tag"))
{
foreach(var field in def.Fields)
{
var tag = _transformFieldName(field.Name);
var optionTypeName = _choiceOptionNeedsWrapper(field)
? _transformFieldName(field.Name) + "Wrapper"
: _getDefinitionName(null, field.Name, field.Type);
sw.Case("Tags." + tag);
sw.WriteLine("Value<{0}>.Save(sink, ({0})value);", optionTypeName);
sw.Break();
}
sw.Default();
sw.WriteLine("throw new Exception();");
sw.Indent--;
}
save.WriteLine("sink.LeaveChoice();");
}
if (root)
{
_generateChoiceTags(cls, def);
_generateChoiceOptions(cls, typeName, def);
}
}
if (!root)
{
_generateChoiceOptions(emitter, typeName, def);
}
}