From e77926f0ed5b0e5e4d888e60fa5410e9e3f25733 Mon Sep 17 00:00:00 2001 From: mugisoba <51015092+mugisoba@users.noreply.github.com> Date: Tue, 27 Jul 2021 02:01:41 +0900 Subject: [PATCH] [C#] Add Union Constructor Utility for ObjectAPI. (#6105) * [C#] add union constructor utility. * add union utility test. * std::tolower -> CharToLower * use std::transform instead * rebase to master. and regenerate test code --- src/idl_gen_csharp.cpp | 26 ++++++++++++------- .../FlatBuffersExampleTests.cs | 20 ++++++++++++++ tests/MyGame/Example/Any.cs | 3 +++ tests/MyGame/Example/AnyAmbiguousAliases.cs | 3 +++ tests/MyGame/Example/AnyUniqueAliases.cs | 3 +++ .../NamespaceA/NamespaceB/UnionInNestedNS.cs | 1 + tests/union_vector/Character.cs | 6 +++++ 7 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index 681ab6d64..3783c89dd 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -1305,19 +1305,27 @@ class CSharpGenerator : public BaseGenerator { code += " }\n\n"; // As code += " public T As() where T : class { return this.Value as T; }\n"; - // As + // As, From for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { auto &ev = **it; if (ev.union_type.base_type == BASE_TYPE_NONE) continue; auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts); - if (ev.union_type.base_type == BASE_TYPE_STRUCT && - ev.union_type.struct_def->attributes.Lookup("private")) { - code += " internal "; - } else { - code += " public "; - } - code += type_name + " As" + ev.name + "() { return this.As<" + type_name + - ">(); }\n"; + std::string accessibility = + (ev.union_type.base_type == BASE_TYPE_STRUCT && + ev.union_type.struct_def->attributes.Lookup("private")) + ? "internal" + : "public"; + // As + code += " " + accessibility + " " + type_name + " As" + ev.name + + "() { return this.As<" + type_name + ">(); }\n"; + // From + auto lower_ev_name = ev.name; + std::transform(lower_ev_name.begin(), lower_ev_name.end(), + lower_ev_name.begin(), CharToLower); + code += " " + accessibility + " static " + union_name + " From" + + ev.name + "(" + type_name + " _" + lower_ev_name + + ") { return new " + union_name + "{ Type = " + enum_def.name + + "." + ev.name + ", Value = _" + lower_ev_name + " }; }\n"; } code += "\n"; // Pack() diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs index b4093d4db..f8c50c6cd 100644 --- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs +++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs @@ -488,6 +488,26 @@ namespace FlatBuffers.Test TestObjectAPI(movie); } + [FlatBuffersTestMethod] + public void TestUnionUtility() + { + var movie = new MovieT + { + MainCharacter = CharacterUnion.FromRapunzel(new RapunzelT { HairLength = 40 }), + Characters = new System.Collections.Generic.List + { + CharacterUnion.FromMuLan(new AttackerT { SwordAttackDamage = 10 }), + CharacterUnion.FromBelle(new BookReaderT { BooksRead = 20 }), + CharacterUnion.FromOther("Chip"), + }, + }; + + var fbb = new FlatBufferBuilder(100); + Movie.FinishMovieBuffer(fbb, Movie.Pack(fbb, movie)); + + TestObjectAPI(Movie.GetRootAsMovie(fbb.DataBuffer)); + } + private void AreEqual(Monster a, MonsterT b) { Assert.AreEqual(a.Hp, b.Hp); diff --git a/tests/MyGame/Example/Any.cs b/tests/MyGame/Example/Any.cs index edf98ef56..2e1717b9e 100644 --- a/tests/MyGame/Example/Any.cs +++ b/tests/MyGame/Example/Any.cs @@ -25,8 +25,11 @@ public class AnyUnion { public T As() where T : class { return this.Value as T; } public MyGame.Example.MonsterT AsMonster() { return this.As(); } + public static AnyUnion FromMonster(MyGame.Example.MonsterT _monster) { return new AnyUnion{ Type = Any.Monster, Value = _monster }; } internal MyGame.Example.TestSimpleTableWithEnumT AsTestSimpleTableWithEnum() { return this.As(); } + internal static AnyUnion FromTestSimpleTableWithEnum(MyGame.Example.TestSimpleTableWithEnumT _testsimpletablewithenum) { return new AnyUnion{ Type = Any.TestSimpleTableWithEnum, Value = _testsimpletablewithenum }; } public MyGame.Example2.MonsterT AsMyGame_Example2_Monster() { return this.As(); } + public static AnyUnion FromMyGame_Example2_Monster(MyGame.Example2.MonsterT _mygame_example2_monster) { return new AnyUnion{ Type = Any.MyGame_Example2_Monster, Value = _mygame_example2_monster }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, AnyUnion _o) { switch (_o.Type) { diff --git a/tests/MyGame/Example/AnyAmbiguousAliases.cs b/tests/MyGame/Example/AnyAmbiguousAliases.cs index 07deadc28..9253cc942 100644 --- a/tests/MyGame/Example/AnyAmbiguousAliases.cs +++ b/tests/MyGame/Example/AnyAmbiguousAliases.cs @@ -25,8 +25,11 @@ public class AnyAmbiguousAliasesUnion { public T As() where T : class { return this.Value as T; } public MyGame.Example.MonsterT AsM1() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM1(MyGame.Example.MonsterT _m1) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M1, Value = _m1 }; } public MyGame.Example.MonsterT AsM2() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM2(MyGame.Example.MonsterT _m2) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M2, Value = _m2 }; } public MyGame.Example.MonsterT AsM3() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM3(MyGame.Example.MonsterT _m3) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M3, Value = _m3 }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, AnyAmbiguousAliasesUnion _o) { switch (_o.Type) { diff --git a/tests/MyGame/Example/AnyUniqueAliases.cs b/tests/MyGame/Example/AnyUniqueAliases.cs index 35949528b..ab3327661 100644 --- a/tests/MyGame/Example/AnyUniqueAliases.cs +++ b/tests/MyGame/Example/AnyUniqueAliases.cs @@ -25,8 +25,11 @@ public class AnyUniqueAliasesUnion { public T As() where T : class { return this.Value as T; } public MyGame.Example.MonsterT AsM() { return this.As(); } + public static AnyUniqueAliasesUnion FromM(MyGame.Example.MonsterT _m) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.M, Value = _m }; } internal MyGame.Example.TestSimpleTableWithEnumT AsTS() { return this.As(); } + internal static AnyUniqueAliasesUnion FromTS(MyGame.Example.TestSimpleTableWithEnumT _ts) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.TS, Value = _ts }; } public MyGame.Example2.MonsterT AsM2() { return this.As(); } + public static AnyUniqueAliasesUnion FromM2(MyGame.Example2.MonsterT _m2) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.M2, Value = _m2 }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, AnyUniqueAliasesUnion _o) { switch (_o.Type) { diff --git a/tests/namespace_test/NamespaceA/NamespaceB/UnionInNestedNS.cs b/tests/namespace_test/NamespaceA/NamespaceB/UnionInNestedNS.cs index 9924f32ba..7d1234f99 100644 --- a/tests/namespace_test/NamespaceA/NamespaceB/UnionInNestedNS.cs +++ b/tests/namespace_test/NamespaceA/NamespaceB/UnionInNestedNS.cs @@ -23,6 +23,7 @@ public class UnionInNestedNSUnion { public T As() where T : class { return this.Value as T; } public NamespaceA.NamespaceB.TableInNestedNST AsTableInNestedNS() { return this.As(); } + public static UnionInNestedNSUnion FromTableInNestedNS(NamespaceA.NamespaceB.TableInNestedNST _tableinnestedns) { return new UnionInNestedNSUnion{ Type = UnionInNestedNS.TableInNestedNS, Value = _tableinnestedns }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, UnionInNestedNSUnion _o) { switch (_o.Type) { diff --git a/tests/union_vector/Character.cs b/tests/union_vector/Character.cs index d067e2221..4978bdcb4 100644 --- a/tests/union_vector/Character.cs +++ b/tests/union_vector/Character.cs @@ -25,11 +25,17 @@ public class CharacterUnion { public T As() where T : class { return this.Value as T; } public AttackerT AsMuLan() { return this.As(); } + public static CharacterUnion FromMuLan(AttackerT _mulan) { return new CharacterUnion{ Type = Character.MuLan, Value = _mulan }; } public RapunzelT AsRapunzel() { return this.As(); } + public static CharacterUnion FromRapunzel(RapunzelT _rapunzel) { return new CharacterUnion{ Type = Character.Rapunzel, Value = _rapunzel }; } public BookReaderT AsBelle() { return this.As(); } + public static CharacterUnion FromBelle(BookReaderT _belle) { return new CharacterUnion{ Type = Character.Belle, Value = _belle }; } public BookReaderT AsBookFan() { return this.As(); } + public static CharacterUnion FromBookFan(BookReaderT _bookfan) { return new CharacterUnion{ Type = Character.BookFan, Value = _bookfan }; } public string AsOther() { return this.As(); } + public static CharacterUnion FromOther(string _other) { return new CharacterUnion{ Type = Character.Other, Value = _other }; } public string AsUnused() { return this.As(); } + public static CharacterUnion FromUnused(string _unused) { return new CharacterUnion{ Type = Character.Unused, Value = _unused }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, CharacterUnion _o) { switch (_o.Type) {