private static void AppendMethod_Set(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); foreach (var member in def.Members) { builder.Append($@" public void Set({member.Type} value) {{ this.{pre_}ValueType = Type.{member.Name}; this.{pre_}{member.Name} = value; }} "); } }
private static void AppendMethod_GetUnderlyingType(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); builder.Append($@" public System.Type GetUnderlyingType()"); if (def.Members.Count < 3) { builder.Append(@" {"); foreach (var member in def.Members) { builder.Append($@" if (this.{pre_}ValueType == Type.{member.Name}) return this.{pre_}{member.Name}.GetType(); "); } builder.Append(@" return this.GetType(); } "); } else { builder.Append($@" {{ switch (this.{pre_}ValueType) {{"); foreach (var member in def.Members) { builder.Append($@" case Type.{member.Name}: return this.{pre_}{member.Name}.GetType();"); } builder.Append(@" } return this.GetType(); } "); } }
private static void AppendMethod_GetHashCode(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); builder.Append($@" public override int GetHashCode() {{ var hash = EqualityComparer<Type>.Default.GetHashCode(this.{pre_}ValueType) * -1521134295; "); if (def.Members.Count < 3) { foreach (var member in def.Members) { builder.Append($@" if (this.{pre_}ValueType == Type.{member.Name}) return hash + EqualityComparer<{member.Type}>.Default.GetHashCode(this.{pre_}{member.Name}); "); } builder.Append(@" return hash; } "); } else { builder.Append($@" switch (this.{pre_}ValueType) {{"); foreach (var member in def.Members) { builder.Append($@" case Type.{member.Name}: return hash + EqualityComparer<{member.Type}>.Default.GetHashCode(this.{pre_}{member.Name});"); } builder.Append(@" } return hash; } "); } }
private static void AppendConstructors(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); var last = def.Members.Count - 1; for (var i = 0; i < def.Members.Count; i++) { var member = def.Members[i]; if (i > 0) { builder.AppendLine(); } builder.Append($@" public {def.Name}({member.Type} value) {{ this.{pre_}ValueType = Type.{member.Name}; "); for (var k = 0; k < def.Members.Count; k++) { if (k == i) { continue; } var memberOther = def.Members[k]; builder.Append($@" this.{pre_}{memberOther.Name} = default;"); } builder.Append($@" this.{pre_}{member.Name} = value; }}"); if (i == last) { builder.AppendLine(); } } }
private static void AppendConstructorTypeParam(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); builder.Append($@" public {def.Name}(Type type) {{ this.{pre_}ValueType = type; "); foreach (var member in def.Members) { builder.Append($@" this.{pre_}{member.Name} = default;"); } builder.Append(@" } "); }
private static void AppendMethod_ToString(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); builder.Append(@" public override string ToString() {"); if (def.Members.Count < 3) { foreach (var member in def.Members) { builder.Append($@" if (this.{pre_}ValueType == Type.{member.Name}) return this.{pre_}{member.Name}.ToString(); "); } builder.Append(@" return string.Empty; }"); } else { builder.Append($@" switch (this.{pre_}ValueType) {{"); foreach (var member in def.Members) { builder.Append($@" case Type.{member.Name}: return this.{pre_}{member.Name}.ToString();"); } builder.Append(@" } return string.Empty; }"); } }
private static void AppendMethod_TryGet(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); foreach (var member in def.Members) { builder.Append($@" public bool TryGet(out {member.Type} value) {{ if (this.{pre_}ValueType != Type.{member.Name}) {{ value = default; return false; }} value = this.{pre_}{member.Name}; return true; }} "); } }
private static void AppendOperator_Implicit(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); var last = def.Members.Count - 1; switch (def.InvalidValueAccess) { case InvalidValueAccess.ThrowException: { for (var i = 0; i < def.Members.Count; i++) { var member = def.Members[i]; if (i <= 0) { builder.AppendLine(); } builder.Append($@" public static implicit operator {def.Name}({member.Type} value) => new {def.Name}(value); "); builder.Append($@" public static implicit operator {member.Type}(in {def.Name} value) {{ if (value.{pre_}ValueType == Type.{member.Name}) return value.{pre_}{member.Name}; throw new InvalidValueAccessException($""Cannot implicitly convert underlying type '{{value.GetUnderlyingType().GetNiceFullName()}}' to '{member.Type}'""); }}"); if (i < last) { builder.AppendLine(); } } break; } case InvalidValueAccess.ReturnDefault: { for (var i = 0; i < def.Members.Count; i++) { var member = def.Members[i]; if (i <= 0) { builder.AppendLine(); } builder.Append($@" public static implicit operator {def.Name}({member.Type} value) => new {def.Name}(value); "); builder.Append($@" public static implicit operator {member.Type}(in {def.Name} value) {{ if (value.{pre_}ValueType == Type.{member.Name}) return value.{pre_}{member.Name}; return default; }}"); if (i < last) { builder.AppendLine(); } } break; } default: { for (var i = 0; i < def.Members.Count; i++) { var member = def.Members[i]; if (i <= 0) { builder.AppendLine(); } builder.Append($@" public static implicit operator {def.Name}({member.Type} value) => new {def.Name}(value); "); builder.Append($@" public static implicit operator {member.Type}(in {def.Name} value) => value.{pre_}{member.Name};"); if (i < last) { builder.AppendLine(); } } break; } } }
private static void AppendMethod_Equals(UnionDefinition def, StringBuilder builder) { var pre_ = def.GetMemberPrefix(); builder.Append($@" public override bool Equals(object obj) => obj is {def.Name} other && Equals(in this, in other); public bool Equals({def.Name} other) => Equals(in this, in other); public bool Equals(in {def.Name} other) => Equals(in this, in other); "); builder.Append($@" public static bool Equals(in {def.Name} a, in {def.Name} b)"); if (def.Members.Count < 3) { builder.Append($@" {{ if (a.{pre_}ValueType != b.{pre_}ValueType) return false; "); foreach (var member in def.Members) { builder.Append($@" if (a.{pre_}ValueType == Type.{member.Name}) return EqualityComparer<{member.Type}>.Default.Equals(a.{pre_}{member.Name}, b.{pre_}{member.Name}); "); } builder.Append(@" return false; } "); } else { builder.Append($@" {{ if (a.{pre_}ValueType != b.{pre_}ValueType) return false; switch (a.{pre_}ValueType) {{"); foreach (var member in def.Members) { builder.Append($@" case Type.{member.Name}: return EqualityComparer<{member.Type}>.Default.Equals(a.{pre_}{member.Name}, b.{pre_}{member.Name});"); } builder.Append(@" } return false; } "); } builder.Append($@" public static bool operator ==(in {def.Name} left, in {def.Name} right) => Equals(in left, in right); public static bool operator !=(in {def.Name} left, in {def.Name} right) => !Equals(in left, in right); "); }