├── Reflection ├── Convert.h ├── Object.h ├── Interface.h ├── ArgumentPack.h ├── Method.cpp ├── Attribute.h ├── Reflection.vcxproj.filters ├── Field.h ├── Reflection.vcxproj ├── Type.h ├── Reflection.cpp ├── Method.h └── Reflection.h ├── Readme.md ├── .gitmodules ├── Test ├── Test.vcxproj.filters ├── main.cpp └── Test.vcxproj ├── Reflection.sln └── .gitignore /Reflection/Convert.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akemimadoka/Reflection/HEAD/Reflection/Convert.h -------------------------------------------------------------------------------- /Reflection/Object.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akemimadoka/Reflection/HEAD/Reflection/Object.h -------------------------------------------------------------------------------- /Reflection/Interface.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akemimadoka/Reflection/HEAD/Reflection/Interface.h -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Reflection 2 | ==== 3 | 作者用于练习C++技巧的一个反射库。 4 | 5 | A reflection library for practising C++ skill. 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "NatsuLib"] 2 | path = NatsuLib 3 | url = https://github.com/akemimadoka/NatsuLib.git 4 | -------------------------------------------------------------------------------- /Reflection/ArgumentPack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Object.h" 3 | #include 4 | 5 | class ArgumentPack 6 | { 7 | public: 8 | template 9 | ArgumentPack(Args&&... args) 10 | : m_Args{ Object::Box(std::forward(args))... } 11 | { 12 | } 13 | ~ArgumentPack(); 14 | 15 | natRefPointer Extract(); 16 | natRefPointer Get(size_t n) const; 17 | natRefPointer GetType(size_t n) const; 18 | size_t Size() const; 19 | 20 | private: 21 | std::deque> m_Args; 22 | }; 23 | -------------------------------------------------------------------------------- /Reflection/Method.cpp: -------------------------------------------------------------------------------- 1 | #include "Method.h" 2 | 3 | ArgumentPack::~ArgumentPack() 4 | { 5 | } 6 | 7 | natRefPointer ArgumentPack::Extract() 8 | { 9 | auto ret = std::move(m_Args.front()); 10 | m_Args.pop_front(); 11 | return ret; 12 | } 13 | 14 | natRefPointer ArgumentPack::Get(size_t n) const 15 | { 16 | return m_Args.at(n); 17 | } 18 | 19 | natRefPointer ArgumentPack::GetType(size_t n) const 20 | { 21 | return m_Args.at(n)->GetType(); 22 | } 23 | 24 | size_t ArgumentPack::Size() const 25 | { 26 | return m_Args.size(); 27 | } 28 | -------------------------------------------------------------------------------- /Test/Test.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /Reflection/Attribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Interface.h" 3 | #include "Object.h" 4 | #include 5 | 6 | #define WITH(...) AttributeSet{ __VA_ARGS__ } 7 | 8 | struct IAttribute 9 | : virtual Object 10 | { 11 | static nStrView GetName() noexcept 12 | { 13 | return "IAttribute"_nv; 14 | } 15 | 16 | natRefPointer GetType() const noexcept override; 17 | }; 18 | 19 | struct AttributeSet 20 | { 21 | template 22 | AttributeSet(Attr&&... attributes) 23 | : Attributes{ make_ref(std::forward(attributes))... } 24 | { 25 | } 26 | 27 | std::vector> Attributes; 28 | }; 29 | 30 | enum class AttributeTarget : uint8_t 31 | { 32 | None = 0x00, 33 | 34 | Class = 0x01, 35 | Constructor = 0x02, 36 | Field = 0x04, 37 | Method = 0x08, 38 | Parameter = 0x10, 39 | ReturnValue = 0x20, 40 | All = 0xFF, 41 | }; 42 | 43 | MAKE_ENUM_CLASS_BITMASK_TYPE(AttributeTarget); 44 | 45 | class AttributeUsage 46 | : public IAttribute 47 | { 48 | public: 49 | AttributeUsage() noexcept 50 | : AttributeUsage(AttributeTarget::All) 51 | { 52 | } 53 | 54 | explicit AttributeUsage(AttributeTarget target) noexcept 55 | : m_Target(target) 56 | { 57 | } 58 | 59 | static nStrView GetName() noexcept 60 | { 61 | return "AttributeUsage"_nv; 62 | } 63 | 64 | natRefPointer GetType() const noexcept override; 65 | 66 | AttributeTarget GetTarget() const noexcept 67 | { 68 | return m_Target; 69 | } 70 | 71 | private: 72 | AttributeTarget m_Target; 73 | }; 74 | -------------------------------------------------------------------------------- /Reflection/Reflection.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 头文件 28 | 29 | 30 | 头文件 31 | 32 | 33 | 头文件 34 | 35 | 36 | 头文件 37 | 38 | 39 | 头文件 40 | 41 | 42 | 头文件 43 | 44 | 45 | 头文件 46 | 47 | 48 | 头文件 49 | 50 | 51 | 头文件 52 | 53 | 54 | -------------------------------------------------------------------------------- /Reflection.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Reflection", "Reflection\Reflection.vcxproj", "{CD34F2BD-67E1-4645-854C-74706CE7A345}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {E4F66019-9964-4B86-B538-E10F66124689} = {E4F66019-9964-4B86-B538-E10F66124689} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test\Test.vcxproj", "{E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {CD34F2BD-67E1-4645-854C-74706CE7A345} = {CD34F2BD-67E1-4645-854C-74706CE7A345} 14 | EndProjectSection 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NatsuLib", "NatsuLib\NatsuLib\NatsuLib.vcxproj", "{E4F66019-9964-4B86-B538-E10F66124689}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|x64 = Debug|x64 21 | Debug|x86 = Debug|x86 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Debug|x64.ActiveCfg = Debug|x64 27 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Debug|x64.Build.0 = Debug|x64 28 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Debug|x86.ActiveCfg = Debug|Win32 29 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Debug|x86.Build.0 = Debug|Win32 30 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Release|x64.ActiveCfg = Release|x64 31 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Release|x64.Build.0 = Release|x64 32 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Release|x86.ActiveCfg = Release|Win32 33 | {CD34F2BD-67E1-4645-854C-74706CE7A345}.Release|x86.Build.0 = Release|Win32 34 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Debug|x64.ActiveCfg = Debug|x64 35 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Debug|x64.Build.0 = Debug|x64 36 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Debug|x86.ActiveCfg = Debug|Win32 37 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Debug|x86.Build.0 = Debug|Win32 38 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Release|x64.ActiveCfg = Release|x64 39 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Release|x64.Build.0 = Release|x64 40 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Release|x86.ActiveCfg = Release|Win32 41 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F}.Release|x86.Build.0 = Release|Win32 42 | {E4F66019-9964-4B86-B538-E10F66124689}.Debug|x64.ActiveCfg = Debug|x64 43 | {E4F66019-9964-4B86-B538-E10F66124689}.Debug|x64.Build.0 = Debug|x64 44 | {E4F66019-9964-4B86-B538-E10F66124689}.Debug|x86.ActiveCfg = Debug|Win32 45 | {E4F66019-9964-4B86-B538-E10F66124689}.Debug|x86.Build.0 = Debug|Win32 46 | {E4F66019-9964-4B86-B538-E10F66124689}.Release|x64.ActiveCfg = Release|x64 47 | {E4F66019-9964-4B86-B538-E10F66124689}.Release|x64.Build.0 = Release|x64 48 | {E4F66019-9964-4B86-B538-E10F66124689}.Release|x86.ActiveCfg = Release|Win32 49 | {E4F66019-9964-4B86-B538-E10F66124689}.Release|x86.Build.0 = Release|Win32 50 | EndGlobalSection 51 | GlobalSection(SolutionProperties) = preSolution 52 | HideSolutionNode = FALSE 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /Reflection/Field.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Interface.h" 3 | #include "Object.h" 4 | #include "Convert.h" 5 | 6 | namespace rdetail_ 7 | { 8 | template 9 | struct FieldSetter 10 | { 11 | static void Set(T& val, natRefPointer const& pObj) 12 | { 13 | val = Convert::ConvertTo>>(pObj)->Unbox>>(); 14 | } 15 | }; 16 | 17 | template 18 | struct FieldSetter> 19 | { 20 | static void Set(natRefPointer& val, natRefPointer const& pObj) 21 | { 22 | if (!pObj) 23 | { 24 | val = nullptr; 25 | } 26 | else 27 | { 28 | auto tmp = static_cast>(pObj); 29 | if (!tmp) 30 | { 31 | tmp = Convert::ConvertTo>>(pObj); 32 | //nat_Throw(ReflectionException, "pObj cannot assign to val."_nv); 33 | } 34 | 35 | val = std::move(tmp); 36 | } 37 | } 38 | }; 39 | 40 | template 41 | struct IsRefPointerImpl 42 | : std::false_type 43 | { 44 | }; 45 | 46 | template 47 | struct IsRefPointerImpl> 48 | : std::true_type 49 | { 50 | }; 51 | } 52 | 53 | template 54 | struct IsRefPointer 55 | : rdetail_::IsRefPointerImpl>> 56 | { 57 | }; 58 | 59 | template 60 | class NonMemberField; 61 | 62 | template 63 | class NonMemberField 64 | : public natRefObjImpl, IField> 65 | { 66 | public: 67 | typedef T* FieldType; 68 | 69 | explicit NonMemberField(AccessSpecifier accessSpecifier, FieldType field) 70 | : m_AccessSpecifier{ accessSpecifier }, m_Field { field } 71 | { 72 | } 73 | 74 | natRefPointer GetType() override 75 | { 76 | return m_Field->GetType(); 77 | } 78 | 79 | AccessSpecifier GetAccessSpecifier() const noexcept override 80 | { 81 | return m_AccessSpecifier; 82 | } 83 | 84 | AccessSpecifier SetAccessSpecifier(AccessSpecifier accessSpecifier) noexcept override 85 | { 86 | return std::exchange(m_AccessSpecifier, accessSpecifier); 87 | } 88 | 89 | bool IsPointer() const noexcept override 90 | { 91 | return IsRefPointer::value; 92 | } 93 | 94 | natRefPointer Read() override 95 | { 96 | return Object::Box(*m_Field); 97 | } 98 | 99 | void Write(natRefPointer value) override 100 | { 101 | //*m_Field = value->Unbox(); 102 | rdetail_::FieldSetter>>::Set(*m_Field, value); 103 | } 104 | 105 | private: 106 | AccessSpecifier m_AccessSpecifier; 107 | FieldType m_Field; 108 | }; 109 | 110 | template 111 | class MemberField; 112 | 113 | template 114 | class MemberField 115 | : public natRefObjImpl, IMemberField> 116 | { 117 | public: 118 | typedef T(Class::*FieldType); 119 | 120 | explicit MemberField(AccessSpecifier accessSpecifier, FieldType field) 121 | : m_AccessSpecifier{ accessSpecifier }, m_Field{ field } 122 | { 123 | } 124 | 125 | natRefPointer GetType() override; 126 | 127 | AccessSpecifier GetAccessSpecifier() const noexcept override 128 | { 129 | return m_AccessSpecifier; 130 | } 131 | 132 | AccessSpecifier SetAccessSpecifier(AccessSpecifier accessSpecifier) noexcept override 133 | { 134 | return std::exchange(m_AccessSpecifier, accessSpecifier); 135 | } 136 | 137 | bool IsPointer() const noexcept override 138 | { 139 | return IsRefPointer::value; 140 | } 141 | 142 | natRefPointer ReadFrom(natRefPointer object) override 143 | { 144 | return Object::Box(object->Unbox().*m_Field); 145 | } 146 | 147 | void WriteFrom(natRefPointer object, natRefPointer value) override 148 | { 149 | //object->Unbox().*m_Field = value->Unbox(); 150 | rdetail_::FieldSetter>>::Set(object->Unbox().*m_Field, value); 151 | } 152 | 153 | private: 154 | AccessSpecifier m_AccessSpecifier; 155 | FieldType m_Field; 156 | }; 157 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /Test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /*DECLARE_REFLECTABLE_INTERFACE(ISerializable) 7 | { 8 | GENERATE_METADATA(ISerializable); 9 | 10 | DECLARE_PURE_VIRTUAL_MEMBER_METHOD(public, ISerializable, , Serialize, , size_t, ); 11 | DECLARE_PURE_VIRTUAL_MEMBER_METHOD(public, ISerializable, , Deserialize, , size_t, ); 12 | }; 13 | 14 | GENERATE_METADATA_DEFINITION(ISerializable); 15 | 16 | DEFINE_PURE_VIRTUAL_MEMBER_METHOD(public, ISerializable, , Serialize, , size_t, ); 17 | DEFINE_PURE_VIRTUAL_MEMBER_METHOD(public, ISerializable, , Deserialize, , size_t, );*/ 18 | 19 | DECLARE_REFLECTABLE_CLASS_WITH_BASE_CLASSES(TestAttribute, IAttribute) 20 | { 21 | GENERATE_METADATA_WITH_BASE_CLASSES(TestAttribute, WITH(AttributeUsage(AttributeTarget::Class)), IAttribute); 22 | 23 | DECLARE_CONST_MEMBER_METHOD(public, TestAttribute, , Test, , int); 24 | }; 25 | 26 | GENERATE_METADATA_DEFINITION_WITH_BASE_CLASSES(TestAttribute, WITH(AttributeUsage(AttributeTarget::Class)), IAttribute); 27 | 28 | DEFINE_CONST_MEMBER_METHOD(public, TestAttribute, , Test, , int)() const 29 | { 30 | return 1; 31 | } 32 | 33 | DECLARE_REFLECTABLE_CLASS(Foo) 34 | { 35 | GENERATE_METADATA(Foo, WITH(TestAttribute())) 36 | 37 | DECLARE_CONSTRUCTOR(public, Foo, explicit, , int); 38 | DECLARE_DEFAULT_COPYCONSTRUCTOR(public, Foo); 39 | DECLARE_DEFAULT_MOVECONSTRUCTOR(public, Foo); 40 | DECLARE_CONST_MEMBER_METHOD(public, Foo, , GetTest, 0, int const&); 41 | DECLARE_CONST_MEMBER_METHOD(public, Foo, , GetTest, 1, int, int const&); 42 | DECLARE_VIRTUAL_MEMBER_METHOD(public, Foo, , Test, , int); 43 | DECLARE_MEMBER_METHOD(public, Foo, , Test1, , void); 44 | 45 | DECLARE_MEMBER_FIELD(private, Foo, int, m_Test); 46 | }; 47 | 48 | GENERATE_METADATA_DEFINITION(Foo, WITH(TestAttribute())); 49 | 50 | DEFINE_CONSTRUCTOR(public, Foo, , , int)(int value) 51 | : m_Test{ value } 52 | { 53 | } 54 | 55 | DEFINE_DEFAULT_COPYCONSTRUCTOR(public, Foo) 56 | DEFINE_DEFAULT_MOVECONSTRUCTOR(public, Foo) 57 | 58 | DEFINE_CONST_MEMBER_METHOD(public, Foo, , GetTest, 0, int const&)() const 59 | { 60 | return m_Test; 61 | } 62 | 63 | DEFINE_CONST_MEMBER_METHOD(public, Foo, , GetTest, 1, int, int const&)(int const& arg) const 64 | { 65 | return m_Test + arg; 66 | } 67 | 68 | DEFINE_VIRTUAL_MEMBER_METHOD(public, Foo, , Test, , int)() 69 | { 70 | return ++m_Test; 71 | } 72 | 73 | DEFINE_MEMBER_METHOD(public, Foo, , Test1, , void)() 74 | { 75 | std::cout << m_Test << std::endl; 76 | } 77 | 78 | DEFINE_MEMBER_FIELD(private, Foo, int, m_Test); 79 | 80 | REGISTER_BOXED_REFOBJECT(natStream); 81 | REGISTER_BOXED_REFOBJECT_DEF(natStream); 82 | 83 | DECLARE_REFLECTABLE_CLASS_WITH_BASE_CLASS(Bar, Foo) 84 | { 85 | GENERATE_METADATA_WITH_BASE_CLASSES(Bar, WITH(), Foo); 86 | 87 | DECLARE_CONSTRUCTOR(public, Bar, explicit, , int); 88 | DECLARE_VIRTUAL_MEMBER_METHOD(public, Bar, , Test, , int); 89 | 90 | DECLARE_MEMBER_METHOD(public, Bar, , BoxedTest, , natRefPointer, natStream&); 91 | }; 92 | 93 | GENERATE_METADATA_DEFINITION_WITH_BASE_CLASSES(Bar, WITH(), Foo); 94 | 95 | DEFINE_CONSTRUCTOR(public, Bar, explicit, , int)(int arg) 96 | : Foo(arg) 97 | { 98 | } 99 | 100 | DEFINE_VIRTUAL_MEMBER_METHOD(public, Bar, , Test, , int)() 101 | { 102 | return Foo::Test() + 1; 103 | } 104 | 105 | DEFINE_MEMBER_METHOD(public, Bar, , BoxedTest, , natRefPointer, natStream&)(natStream& stream) 106 | { 107 | static_cast(stream); 108 | return Box(); 109 | } 110 | 111 | struct haha 112 | { 113 | int a; 114 | }; 115 | 116 | REGISTER_BOXED_OBJECT(haha); 117 | REGISTER_BOXED_OBJECT_DEF(haha); 118 | 119 | int main() 120 | { 121 | try 122 | { 123 | for (auto&& item : Reflection::GetInstance().GetTypes()) 124 | { 125 | std::wcout << item->GetName() << std::endl; 126 | } 127 | 128 | std::wcout << typeof(int)->GetName() << std::endl; 129 | 130 | auto type = typeofname("Foo"_nv); 131 | std::wcout << type->GetAttribute()->Test() << std::endl; 132 | auto pFoo = type->Construct({ 1 }); 133 | std::wcout << pFoo->ToString() << std::endl << type->InvokeMember(pFoo, "GetTest"_nv, {})->ToString() << std::endl << type->InvokeMember(pFoo, "GetTest"_nv, { 1 })->ToString() << std::endl; 134 | 135 | std::wcout << type->InvokeMember(pFoo, "Test"_nv, {})->ToString() << std::endl; 136 | std::wcout << type->ReadMemberField(pFoo, "m_Test"_nv)->ToString() << std::endl; 137 | 138 | decltype(auto) UnboxedFoo = pFoo->Unbox(); 139 | std::wcout << UnboxedFoo.GetTest() << std::endl; 140 | 141 | auto type2 = typeofname("Bar"_nv); 142 | auto pBar = type2->Construct({ 1 }); 143 | std::wcout << type2->InvokeMember(pBar, "Test"_nv, {})->ToString() << std::endl << std::endl; 144 | 145 | natFileStream a{ "main.cpp"_nv, false, false }; 146 | type2->InvokeMember(pBar, "BoxedTest"_nv, { natRefPointer{ &a } }); 147 | 148 | for (auto&& item : type2->GetBaseClasses()) 149 | { 150 | std::wcout << item->GetName() << std::endl; 151 | } 152 | 153 | std::wcout << std::endl; 154 | 155 | for (auto&& item : type2->GetMemberMethods() 156 | .where([](std::pair> const& method) 157 | { 158 | return method.second->GetAccessSpecifier() == AccessSpecifier::AccessSpecifier_public; 159 | })) 160 | { 161 | std::wcout << item.first << std::endl; 162 | } 163 | 164 | std::wcout << std::endl; 165 | 166 | std::vector>> members{}; 167 | type2->EnumMember(true, [&members](nStrView name, bool isMethod, natRefPointer objectType) 168 | { 169 | members.emplace_back(isMethod, name, objectType); 170 | return false; 171 | }); 172 | for (auto&& item : members) 173 | { 174 | if (std::get<0>(item)) 175 | { 176 | std::wcout << "Method : " << std::get<1>(item) << std::endl; 177 | } 178 | else 179 | { 180 | std::wcout << "Field : " << std::get<1>(item) << " (" << std::get<2>(item)->GetName() << ")" << std::endl; 181 | } 182 | } 183 | 184 | std::wcout << std::boolalpha << type2->IsExtendFrom(type) << std::endl << type2->IsBoxed() << std::endl << (*type2->GetMemberFields().where([](auto&& pair) { return pair.first == "m_Test"_nv; }).begin()).second->GetType()->IsBoxed() << std::endl; 185 | 186 | std::wcout << typeof(RefString)->Construct({ "Test!"_nv })->ToString() << std::endl; 187 | 188 | // Benchmark 189 | /*auto Test = type2->GetMemberMethod("Test"_nv, {}); 190 | ArgumentPack args{}; 191 | 192 | auto time = std::chrono::high_resolution_clock::now(); 193 | for (size_t i = 0; i < 1000000; ++i) 194 | { 195 | Test->Invoke(pBar, args); 196 | } 197 | std::wcout << std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - time).count() << std::endl; 198 | auto bar = static_cast>(pBar); 199 | time = std::chrono::high_resolution_clock::now(); 200 | for (size_t i = 0; i < 1000000; ++i) 201 | { 202 | bar->Test(); 203 | } 204 | std::wcout << std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - time).count() << std::endl;*/ 205 | } 206 | catch (ReflectionException& e) 207 | { 208 | std::wcerr << natUtil::FormatString("Exception caught from {0}, file \"{1}\" line {2},\nDescription: {3}"_nv, e.GetSource(), e.GetFile(), e.GetLine(), e.GetDesc()) << std::endl; 209 | #ifdef EnableExceptionStackTrace 210 | std::wcerr << "Call stack:"_nv << std::endl; 211 | for (size_t i = 0; i < e.GetStackWalker().GetFrameCount(); ++i) 212 | { 213 | auto&& symbol = e.GetStackWalker().GetSymbol(i); 214 | std::wcerr << natUtil::FormatString("{3}: (0x%p) {4} at address 0x%p (file {5}:{6} at address 0x%p)"_nv, symbol.OriginalAddress, reinterpret_cast(symbol.SymbolAddress), reinterpret_cast(symbol.SourceFileAddress), i, symbol.SymbolName, symbol.SourceFileName, symbol.SourceFileLine) << std::endl; 215 | } 216 | #endif 217 | } 218 | catch (std::exception& e) 219 | { 220 | std::cout << nStrView{ e.what() } << std::endl; 221 | } 222 | 223 | #ifdef _WIN32 224 | system("pause"); 225 | #else 226 | std::cin.get(); 227 | #endif 228 | } 229 | -------------------------------------------------------------------------------- /Test/Test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {E4F6EA81-1F22-4756-B9CD-BFAB05A4764F} 23 | Win32Proj 24 | Test 25 | 10.0.16299.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | $(SolutionDir)Reflection;$(SolutionDir)NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 93 | stdcpplatest 94 | 95 | 96 | Console 97 | true 98 | $(SolutionDir)Reflection\bin\$(Platform)\$(Configuration);$(SolutionDir)NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 99 | Reflection.lib;NatsuLib.lib;%(AdditionalDependencies) 100 | 101 | 102 | 103 | 104 | 105 | 106 | Level3 107 | Disabled 108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | $(SolutionDir)Reflection;$(SolutionDir)NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 111 | stdcpplatest 112 | 113 | 114 | Console 115 | true 116 | $(SolutionDir)Reflection\bin\$(Platform)\$(Configuration);$(SolutionDir)NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 117 | Reflection.lib;NatsuLib.lib;%(AdditionalDependencies) 118 | 119 | 120 | 121 | 122 | Level3 123 | 124 | 125 | MaxSpeed 126 | true 127 | true 128 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 129 | true 130 | $(SolutionDir)Reflection;$(SolutionDir)NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 131 | stdcpplatest 132 | 133 | 134 | Console 135 | true 136 | true 137 | true 138 | $(SolutionDir)Reflection\bin\$(Platform)\$(Configuration);$(SolutionDir)NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 139 | Reflection.lib;NatsuLib.lib;%(AdditionalDependencies) 140 | 141 | 142 | 143 | 144 | Level3 145 | 146 | 147 | MaxSpeed 148 | true 149 | true 150 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 151 | true 152 | $(SolutionDir)Reflection;$(SolutionDir)NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 153 | stdcpplatest 154 | 155 | 156 | Console 157 | true 158 | true 159 | true 160 | $(SolutionDir)Reflection\bin\$(Platform)\$(Configuration);$(SolutionDir)NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 161 | Reflection.lib;NatsuLib.lib;%(AdditionalDependencies) 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /Reflection/Reflection.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {CD34F2BD-67E1-4645-854C-74706CE7A345} 23 | Win32Proj 24 | Reflection 25 | 10.0.16299.0 26 | 27 | 28 | 29 | StaticLibrary 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | StaticLibrary 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | StaticLibrary 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | StaticLibrary 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | bin\$(Platform)\$(Configuration)\ 75 | obj\$(Platform)\$(Configuration)\ 76 | 77 | 78 | true 79 | bin\$(Platform)\$(Configuration)\ 80 | obj\$(Platform)\$(Configuration)\ 81 | 82 | 83 | false 84 | bin\$(Platform)\$(Configuration)\ 85 | obj\$(Platform)\$(Configuration)\ 86 | 87 | 88 | false 89 | bin\$(Platform)\$(Configuration)\ 90 | obj\$(Platform)\$(Configuration)\ 91 | 92 | 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 99 | true 100 | $(ProjectDir)..\NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 101 | /bigobj %(AdditionalOptions) 102 | stdcpplatest 103 | 104 | 105 | Console 106 | true 107 | ..\..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 108 | NatsuLib.lib;%(AdditionalDependencies) 109 | 110 | 111 | NatsuLib.lib;%(AdditionalDependencies) 112 | 113 | 114 | $(ProjectDir)..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 115 | 116 | 117 | 118 | 119 | 120 | 121 | Level3 122 | Disabled 123 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | $(ProjectDir)..\NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 126 | /bigobj %(AdditionalOptions) 127 | stdcpplatest 128 | 129 | 130 | Console 131 | true 132 | ..\..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 133 | NatsuLib.lib;%(AdditionalDependencies) 134 | 135 | 136 | NatsuLib.lib;%(AdditionalDependencies) 137 | 138 | 139 | $(ProjectDir)..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 140 | 141 | 142 | 143 | 144 | Level3 145 | 146 | 147 | MaxSpeed 148 | true 149 | true 150 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 151 | true 152 | $(ProjectDir)..\NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 153 | /bigobj %(AdditionalOptions) 154 | stdcpplatest 155 | 156 | 157 | Console 158 | true 159 | true 160 | true 161 | ..\..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 162 | NatsuLib.lib;%(AdditionalDependencies) 163 | 164 | 165 | NatsuLib.lib;%(AdditionalDependencies) 166 | 167 | 168 | $(ProjectDir)..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 169 | 170 | 171 | 172 | 173 | Level3 174 | 175 | 176 | MaxSpeed 177 | true 178 | true 179 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 180 | true 181 | $(ProjectDir)..\NatsuLib\NatsuLib;%(AdditionalIncludeDirectories) 182 | /bigobj %(AdditionalOptions) 183 | stdcpplatest 184 | 185 | 186 | Console 187 | true 188 | true 189 | true 190 | ..\..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 191 | NatsuLib.lib;%(AdditionalDependencies) 192 | 193 | 194 | NatsuLib.lib;%(AdditionalDependencies) 195 | 196 | 197 | $(ProjectDir)..\NatsuLib\NatsuLib\bin\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /Reflection/Type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Interface.h" 3 | #include "Attribute.h" 4 | #include 5 | #include 6 | 7 | #define STRIMPL_(x) #x##_nv 8 | #define STR(x) STRIMPL_(x) 9 | #define CONSTRUCTOR_NAME Constructor 10 | #define CONSTRUCTOR_NAME_STR STR(Constructor) 11 | 12 | template 13 | class Type 14 | : public natRefObjImpl, IType> 15 | { 16 | public: 17 | typedef T OriginType; 18 | 19 | void UncheckedRegisterAttributes(AttributeSet&& attributes) 20 | { 21 | m_Attributes = move(attributes.Attributes); 22 | } 23 | 24 | void RegisterAttributes(AttributeSet&& attributes) override 25 | { 26 | for (auto&& item : attributes.Attributes) 27 | { 28 | const auto type = item->GetType(); 29 | const auto usage = type->GetAttribute(); 30 | if (usage && (usage->GetTarget() & AttributeTarget::Class) == AttributeTarget::None) 31 | { 32 | nat_Throw(ReflectionException, "Attribute {0} cannot apply to class."_nv, type->GetName()); 33 | } 34 | } 35 | 36 | UncheckedRegisterAttributes(std::move(attributes)); 37 | } 38 | 39 | void RegisterBaseClasses(std::initializer_list> baseClasses) override; 40 | 41 | void RegisterNonMemberMethod(nStrView name, natRefPointer method) override 42 | { 43 | m_NonMemberMethodMap.emplace(name, method); 44 | } 45 | 46 | void RegisterMemberMethod(nStrView name, natRefPointer method) override 47 | { 48 | m_MemberMethodMap.emplace(name, method); 49 | } 50 | 51 | void RegisterNonMemberField(nStrView name, natRefPointer field) override 52 | { 53 | m_NonMemberFieldMap.emplace(name, field); 54 | } 55 | 56 | void RegisterMemberField(nStrView name, natRefPointer field) override 57 | { 58 | m_MemberFieldMap.emplace(name, field); 59 | } 60 | 61 | nStrView GetName() const noexcept override 62 | { 63 | return T::GetName(); 64 | } 65 | 66 | bool IsBoxed() const noexcept override; 67 | 68 | natRefPointer Construct(ArgumentPack const& args) override 69 | { 70 | return InvokeNonMember(CONSTRUCTOR_NAME_STR, args); 71 | } 72 | 73 | size_t GetBaseClassesCount() const noexcept override 74 | { 75 | return m_BaseClasses.size(); 76 | } 77 | 78 | natRefPointer GetBaseClass(size_t n) const noexcept override 79 | { 80 | return m_BaseClasses.at(n); 81 | } 82 | 83 | Linq> GetBaseClasses() const noexcept override 84 | { 85 | return from(m_BaseClasses); 86 | } 87 | 88 | natRefPointer InvokeNonMember(nStrView name, ArgumentPack const& args) override 89 | { 90 | const auto range = m_NonMemberMethodMap.equal_range(name); 91 | if (range.first == range.second) 92 | { 93 | for (auto&& item : m_BaseClasses) 94 | { 95 | try 96 | { 97 | return item->InvokeNonMember(name, args); 98 | } 99 | catch (...) 100 | { 101 | } 102 | } 103 | nat_Throw(ReflectionException, "No such nonmember method named {0}."_nv, name); 104 | } 105 | 106 | for (auto&& item : make_range(range.first, range.second)) 107 | { 108 | if (item.second->CompatWith(args)) 109 | { 110 | return item.second->Invoke(args); 111 | } 112 | } 113 | 114 | nat_Throw(ReflectionException, "None of overloaded nonmember method named {0} can be invoked with given args."_nv, name); 115 | } 116 | 117 | natRefPointer InvokeMember(natRefPointer object, nStrView name, ArgumentPack const& args) override 118 | { 119 | const auto range = m_MemberMethodMap.equal_range(name); 120 | if (range.first == range.second) 121 | { 122 | for (auto&& item : m_BaseClasses) 123 | { 124 | try 125 | { 126 | return item->InvokeMember(object, name, args); 127 | } 128 | catch (...) 129 | { 130 | // if all, rethrow below 131 | } 132 | } 133 | nat_Throw(ReflectionException, "No such member method named {0}."_nv, name); 134 | } 135 | 136 | for (auto&& item : make_range(range.first, range.second)) 137 | { 138 | if (item.second->CompatWith(object, args)) 139 | { 140 | return item.second->Invoke(object, args); 141 | } 142 | } 143 | 144 | nat_Throw(ReflectionException, "None of overloaded member method named {0} can be invoked with given args."_nv, name); 145 | } 146 | 147 | natRefPointer GetNonMemberMethod(nStrView name, std::initializer_list> const& argTypes) override 148 | { 149 | const auto range = m_NonMemberMethodMap.equal_range(name); 150 | if (range.first == range.second) 151 | { 152 | for (auto&& item : m_BaseClasses) 153 | { 154 | if (auto method = item->GetNonMemberMethod(name, argTypes)) 155 | { 156 | return method; 157 | } 158 | } 159 | return {}; 160 | } 161 | 162 | for (auto&& item : make_range(range.first, range.second)) 163 | { 164 | if (item.second->GetArgumentCount() == argTypes.size()) 165 | { 166 | for (size_t i = 0; i < argTypes.size(); ++i) 167 | { 168 | if (!item.second->GetArgumentType(i)->Equal(std::next(begin(argTypes), i)->Get())) 169 | { 170 | goto NotMatch; 171 | } 172 | } 173 | return item.second; 174 | } 175 | NotMatch: 176 | continue; 177 | } 178 | 179 | return {}; 180 | } 181 | 182 | natRefPointer GetMemberMethod(nStrView name, std::initializer_list> const& argTypes) override 183 | { 184 | const auto range = m_MemberMethodMap.equal_range(name); 185 | if (range.first == range.second) 186 | { 187 | for (auto&& item : m_BaseClasses) 188 | { 189 | if (auto method = item->GetMemberMethod(name, argTypes)) 190 | { 191 | return method; 192 | } 193 | } 194 | return {}; 195 | } 196 | 197 | for (auto&& item : make_range(range.first, range.second)) 198 | { 199 | if (item.second->GetArgumentCount() == size(argTypes)) 200 | { 201 | for (size_t i = 0; i < size(argTypes); ++i) 202 | { 203 | if (!item.second->GetArgumentType(i)->Equal(std::next(begin(argTypes), i)->Get())) 204 | { 205 | goto NotMatch; 206 | } 207 | } 208 | return item.second; 209 | } 210 | NotMatch: 211 | continue; 212 | } 213 | 214 | return {}; 215 | } 216 | 217 | bool IsNonMemberFieldPointer(nStrView name) override 218 | { 219 | const auto iter = m_NonMemberFieldMap.find(name); 220 | if (iter == m_NonMemberFieldMap.end()) 221 | { 222 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 223 | } 224 | 225 | return iter->second->IsPointer(); 226 | } 227 | 228 | bool IsMemberFieldPointer(nStrView name) override 229 | { 230 | const auto iter = m_MemberFieldMap.find(name); 231 | if (iter == m_MemberFieldMap.end()) 232 | { 233 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 234 | } 235 | 236 | return iter->second->IsPointer(); 237 | } 238 | 239 | natRefPointer ReadNonMemberField(nStrView name) override 240 | { 241 | const auto iter = m_NonMemberFieldMap.find(name); 242 | if (iter == m_NonMemberFieldMap.end()) 243 | { 244 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 245 | } 246 | 247 | return iter->second->Read(); 248 | } 249 | 250 | natRefPointer ReadMemberField(natRefPointer object, nStrView name) override 251 | { 252 | const auto iter = m_MemberFieldMap.find(name); 253 | if (iter == m_MemberFieldMap.end()) 254 | { 255 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 256 | } 257 | 258 | return iter->second->ReadFrom(object); 259 | } 260 | 261 | void WriteNonMemberField(nStrView name, natRefPointer value) override 262 | { 263 | const auto iter = m_NonMemberFieldMap.find(name); 264 | if (iter == m_NonMemberFieldMap.end()) 265 | { 266 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 267 | } 268 | 269 | iter->second->Write(value); 270 | } 271 | 272 | void WriteMemberField(natRefPointer object, nStrView name, natRefPointer value) override 273 | { 274 | const auto iter = m_MemberFieldMap.find(name); 275 | if (iter == m_MemberFieldMap.end()) 276 | { 277 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 278 | } 279 | 280 | iter->second->WriteFrom(object, value); 281 | } 282 | 283 | natRefPointer GetNonMemberField(nStrView name) override 284 | { 285 | const auto iter = m_NonMemberFieldMap.find(name); 286 | if (iter == m_NonMemberFieldMap.end()) 287 | { 288 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 289 | } 290 | 291 | return iter->second; 292 | } 293 | 294 | natRefPointer GetMemberField(nStrView name) override 295 | { 296 | const auto iter = m_MemberFieldMap.find(name); 297 | if (iter == m_MemberFieldMap.end()) 298 | { 299 | nat_Throw(ReflectionException, "No such member field named {0}."_nv, name); 300 | } 301 | 302 | return iter->second; 303 | } 304 | 305 | bool EnumNonMember(bool recurse, Delegate)> enumFunc) const override 306 | { 307 | for (auto&& item : m_NonMemberMethodMap) 308 | { 309 | if (enumFunc(item.first.GetView(), true, {})) 310 | { 311 | return true; 312 | } 313 | } 314 | for (auto&& item : m_NonMemberFieldMap) 315 | { 316 | if (enumFunc(item.first.GetView(), false, item.second->GetType())) 317 | { 318 | return true; 319 | } 320 | } 321 | if (recurse) 322 | { 323 | for (auto&& item : m_BaseClasses) 324 | { 325 | if (item->EnumNonMember(true, enumFunc)) 326 | { 327 | return true; 328 | } 329 | } 330 | } 331 | 332 | return false; 333 | } 334 | 335 | Linq>> GetNonMemberMethods() const noexcept override 336 | { 337 | Linq>> ret = from(m_NonMemberMethodMap); 338 | for (auto&& item : m_BaseClasses) 339 | { 340 | ret = ret.concat(item->GetNonMemberMethods()); 341 | } 342 | return ret; 343 | } 344 | 345 | Linq>> GetNonMemberFields() const noexcept override 346 | { 347 | Linq>> ret = from(m_NonMemberFieldMap); 348 | for (auto&& item : m_BaseClasses) 349 | { 350 | ret = ret.concat(item->GetNonMemberFields()); 351 | } 352 | return ret; 353 | } 354 | 355 | bool EnumMember(bool recurse, Delegate)> enumFunc) const override 356 | { 357 | for (auto&& item : m_MemberMethodMap) 358 | { 359 | if (enumFunc(item.first.GetView(), true, {})) 360 | { 361 | return true; 362 | } 363 | } 364 | for (auto&& item : m_MemberFieldMap) 365 | { 366 | if (enumFunc(item.first.GetView(), false, item.second->GetType())) 367 | { 368 | return true; 369 | } 370 | } 371 | if (recurse) 372 | { 373 | for (auto&& item : m_BaseClasses) 374 | { 375 | if (item->EnumMember(true, enumFunc)) 376 | { 377 | return true; 378 | } 379 | } 380 | } 381 | 382 | return false; 383 | } 384 | 385 | Linq>> GetMemberMethods() const noexcept override 386 | { 387 | Linq>> ret = from(m_MemberMethodMap); 388 | for (auto&& item : m_BaseClasses) 389 | { 390 | ret = ret.concat(item->GetMemberMethods()); 391 | } 392 | return ret; 393 | } 394 | 395 | Linq>> GetMemberFields() const noexcept override 396 | { 397 | Linq>> ret = from(m_MemberFieldMap); 398 | for (auto&& item : m_BaseClasses) 399 | { 400 | ret = ret.concat(item->GetMemberFields()); 401 | } 402 | return ret; 403 | } 404 | 405 | std::type_index GetTypeIndex() const noexcept override 406 | { 407 | return typeid(T); 408 | } 409 | 410 | bool Equal(const IType* other) const noexcept override 411 | { 412 | return GetTypeIndex() == other->GetTypeIndex(); 413 | } 414 | 415 | bool IsExtendFrom(natRefPointer type) const override 416 | { 417 | if (!type) 418 | { 419 | return false; 420 | } 421 | 422 | for (auto&& item : m_BaseClasses) 423 | { 424 | if (item->Equal(type.Get()) || item->IsExtendFrom(type)) 425 | { 426 | return true; 427 | } 428 | } 429 | 430 | return false; 431 | } 432 | 433 | bool HasAttribute(std::type_index type) const override 434 | { 435 | for (auto&& item : m_Attributes) 436 | { 437 | if (type == typeid(*item)) 438 | { 439 | return true; 440 | } 441 | } 442 | 443 | return false; 444 | } 445 | 446 | natRefPointer GetAttribute(std::type_index type) const override 447 | { 448 | for (auto&& item : m_Attributes) 449 | { 450 | if (type == typeid(*item)) 451 | { 452 | return item; 453 | } 454 | } 455 | 456 | return {}; 457 | } 458 | 459 | private: 460 | std::vector> m_Attributes; 461 | std::vector> m_BaseClasses; 462 | std::unordered_multimap> m_NonMemberMethodMap; 463 | std::unordered_multimap> m_MemberMethodMap; 464 | std::unordered_map> m_NonMemberFieldMap; 465 | std::unordered_map> m_MemberFieldMap; 466 | }; 467 | -------------------------------------------------------------------------------- /Reflection/Reflection.cpp: -------------------------------------------------------------------------------- 1 | #include "Reflection.h" 2 | 3 | #ifdef _WIN32 4 | #ifdef _UNICODE 5 | #define toTString std::to_wstring 6 | typedef WideStringView TStrView; 7 | #else 8 | #define toTString std::to_string 9 | typedef AnsiStringView TStrView; 10 | #endif 11 | #else 12 | #define toTString std::to_string 13 | typedef U8StringView TStrView; 14 | #endif 15 | 16 | Reflection& Reflection::GetInstance() 17 | { 18 | static Reflection s_Instance; 19 | return s_Instance; 20 | } 21 | 22 | natRefPointer Reflection::GetType(nStrView typeName) 23 | { 24 | for (auto&& item : m_TypeTable) 25 | { 26 | if (item.second->GetName() == typeName) 27 | { 28 | return item.second; 29 | } 30 | } 31 | 32 | nat_Throw(ReflectionException, "Type not found."_nv); 33 | } 34 | 35 | Linq> Reflection::GetTypes() const 36 | { 37 | return from(m_TypeTable).select([](auto&& pair) -> natRefPointer const& { return pair.second; }); 38 | } 39 | 40 | natRefPointer IAttribute::GetType() const noexcept 41 | { 42 | return typeof(IAttribute); 43 | } 44 | 45 | natRefPointer AttributeUsage::GetType() const noexcept 46 | { 47 | return typeof(AttributeUsage); 48 | } 49 | 50 | #undef INITIALIZEBOXEDOBJECT 51 | #define INITIALIZEBOXEDOBJECT(type, alias) template class BoxedObject 52 | 53 | INITIALIZEBOXEDOBJECT(bool, Bool); 54 | INITIALIZEBOXEDOBJECT(char, Char); 55 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 56 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 57 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 58 | INITIALIZEBOXEDOBJECT(int16_t, Short); 59 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 60 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 61 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 62 | INITIALIZEBOXEDOBJECT(int64_t, Long); 63 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 64 | INITIALIZEBOXEDOBJECT(float, Float); 65 | INITIALIZEBOXEDOBJECT(double, Double); 66 | INITIALIZEBOXEDOBJECT(nString, RefString); 67 | INITIALIZEBOXEDOBJECT(void, Void); 68 | 69 | #undef INITIALIZEBOXEDOBJECT 70 | #define INITIALIZEBOXEDOBJECT(type, alias) template <> Reflection::ReflectionNonMemberMethodRegister INITIALIZEBOXEDOBJECTFOR::s_BoxedObject_Constructor_##type##_ = { AccessSpecifier::AccessSpecifier_public, "Constructor"_nv, static_cast(*)(type)>(&INITIALIZEBOXEDOBJECTFOR::Constructor) } 71 | 72 | #undef INITIALIZEBOXEDOBJECTFOR 73 | #define INITIALIZEBOXEDOBJECTFOR Bool 74 | 75 | INITIALIZEBOXEDOBJECT(bool, Bool); 76 | INITIALIZEBOXEDOBJECT(char, Char); 77 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 78 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 79 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 80 | INITIALIZEBOXEDOBJECT(int16_t, Short); 81 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 82 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 83 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 84 | INITIALIZEBOXEDOBJECT(int64_t, Long); 85 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 86 | INITIALIZEBOXEDOBJECT(float, Float); 87 | INITIALIZEBOXEDOBJECT(double, Double); 88 | 89 | #undef INITIALIZEBOXEDOBJECTFOR 90 | #define INITIALIZEBOXEDOBJECTFOR Char 91 | 92 | INITIALIZEBOXEDOBJECT(bool, Bool); 93 | INITIALIZEBOXEDOBJECT(char, Char); 94 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 95 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 96 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 97 | INITIALIZEBOXEDOBJECT(int16_t, Short); 98 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 99 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 100 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 101 | INITIALIZEBOXEDOBJECT(int64_t, Long); 102 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 103 | INITIALIZEBOXEDOBJECT(float, Float); 104 | INITIALIZEBOXEDOBJECT(double, Double); 105 | 106 | #undef INITIALIZEBOXEDOBJECTFOR 107 | #define INITIALIZEBOXEDOBJECTFOR WChar 108 | 109 | INITIALIZEBOXEDOBJECT(bool, Bool); 110 | INITIALIZEBOXEDOBJECT(char, Char); 111 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 112 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 113 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 114 | INITIALIZEBOXEDOBJECT(int16_t, Short); 115 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 116 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 117 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 118 | INITIALIZEBOXEDOBJECT(int64_t, Long); 119 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 120 | INITIALIZEBOXEDOBJECT(float, Float); 121 | INITIALIZEBOXEDOBJECT(double, Double); 122 | 123 | #undef INITIALIZEBOXEDOBJECTFOR 124 | #define INITIALIZEBOXEDOBJECTFOR SByte 125 | 126 | INITIALIZEBOXEDOBJECT(bool, Bool); 127 | INITIALIZEBOXEDOBJECT(char, Char); 128 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 129 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 130 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 131 | INITIALIZEBOXEDOBJECT(int16_t, Short); 132 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 133 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 134 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 135 | INITIALIZEBOXEDOBJECT(int64_t, Long); 136 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 137 | INITIALIZEBOXEDOBJECT(float, Float); 138 | INITIALIZEBOXEDOBJECT(double, Double); 139 | 140 | #undef INITIALIZEBOXEDOBJECTFOR 141 | #define INITIALIZEBOXEDOBJECTFOR Byte 142 | 143 | INITIALIZEBOXEDOBJECT(bool, Bool); 144 | INITIALIZEBOXEDOBJECT(char, Char); 145 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 146 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 147 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 148 | INITIALIZEBOXEDOBJECT(int16_t, Short); 149 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 150 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 151 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 152 | INITIALIZEBOXEDOBJECT(int64_t, Long); 153 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 154 | INITIALIZEBOXEDOBJECT(float, Float); 155 | INITIALIZEBOXEDOBJECT(double, Double); 156 | 157 | #undef INITIALIZEBOXEDOBJECTFOR 158 | #define INITIALIZEBOXEDOBJECTFOR Short 159 | 160 | INITIALIZEBOXEDOBJECT(bool, Bool); 161 | INITIALIZEBOXEDOBJECT(char, Char); 162 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 163 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 164 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 165 | INITIALIZEBOXEDOBJECT(int16_t, Short); 166 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 167 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 168 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 169 | INITIALIZEBOXEDOBJECT(int64_t, Long); 170 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 171 | INITIALIZEBOXEDOBJECT(float, Float); 172 | INITIALIZEBOXEDOBJECT(double, Double); 173 | 174 | #undef INITIALIZEBOXEDOBJECTFOR 175 | #define INITIALIZEBOXEDOBJECTFOR UShort 176 | 177 | INITIALIZEBOXEDOBJECT(bool, Bool); 178 | INITIALIZEBOXEDOBJECT(char, Char); 179 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 180 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 181 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 182 | INITIALIZEBOXEDOBJECT(int16_t, Short); 183 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 184 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 185 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 186 | INITIALIZEBOXEDOBJECT(int64_t, Long); 187 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 188 | INITIALIZEBOXEDOBJECT(float, Float); 189 | INITIALIZEBOXEDOBJECT(double, Double); 190 | 191 | #undef INITIALIZEBOXEDOBJECTFOR 192 | #define INITIALIZEBOXEDOBJECTFOR Integer 193 | 194 | INITIALIZEBOXEDOBJECT(bool, Bool); 195 | INITIALIZEBOXEDOBJECT(char, Char); 196 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 197 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 198 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 199 | INITIALIZEBOXEDOBJECT(int16_t, Short); 200 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 201 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 202 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 203 | INITIALIZEBOXEDOBJECT(int64_t, Long); 204 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 205 | INITIALIZEBOXEDOBJECT(float, Float); 206 | INITIALIZEBOXEDOBJECT(double, Double); 207 | 208 | #undef INITIALIZEBOXEDOBJECTFOR 209 | #define INITIALIZEBOXEDOBJECTFOR UInteger 210 | 211 | INITIALIZEBOXEDOBJECT(bool, Bool); 212 | INITIALIZEBOXEDOBJECT(char, Char); 213 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 214 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 215 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 216 | INITIALIZEBOXEDOBJECT(int16_t, Short); 217 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 218 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 219 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 220 | INITIALIZEBOXEDOBJECT(int64_t, Long); 221 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 222 | INITIALIZEBOXEDOBJECT(float, Float); 223 | INITIALIZEBOXEDOBJECT(double, Double); 224 | 225 | #undef INITIALIZEBOXEDOBJECTFOR 226 | #define INITIALIZEBOXEDOBJECTFOR Long 227 | 228 | INITIALIZEBOXEDOBJECT(bool, Bool); 229 | INITIALIZEBOXEDOBJECT(char, Char); 230 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 231 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 232 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 233 | INITIALIZEBOXEDOBJECT(int16_t, Short); 234 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 235 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 236 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 237 | INITIALIZEBOXEDOBJECT(int64_t, Long); 238 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 239 | INITIALIZEBOXEDOBJECT(float, Float); 240 | INITIALIZEBOXEDOBJECT(double, Double); 241 | 242 | #undef INITIALIZEBOXEDOBJECTFOR 243 | #define INITIALIZEBOXEDOBJECTFOR ULong 244 | 245 | INITIALIZEBOXEDOBJECT(bool, Bool); 246 | INITIALIZEBOXEDOBJECT(char, Char); 247 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 248 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 249 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 250 | INITIALIZEBOXEDOBJECT(int16_t, Short); 251 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 252 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 253 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 254 | INITIALIZEBOXEDOBJECT(int64_t, Long); 255 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 256 | INITIALIZEBOXEDOBJECT(float, Float); 257 | INITIALIZEBOXEDOBJECT(double, Double); 258 | 259 | #undef INITIALIZEBOXEDOBJECTFOR 260 | #define INITIALIZEBOXEDOBJECTFOR Float 261 | 262 | INITIALIZEBOXEDOBJECT(bool, Bool); 263 | INITIALIZEBOXEDOBJECT(char, Char); 264 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 265 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 266 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 267 | INITIALIZEBOXEDOBJECT(int16_t, Short); 268 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 269 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 270 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 271 | INITIALIZEBOXEDOBJECT(int64_t, Long); 272 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 273 | INITIALIZEBOXEDOBJECT(float, Float); 274 | INITIALIZEBOXEDOBJECT(double, Double); 275 | 276 | #undef INITIALIZEBOXEDOBJECTFOR 277 | #define INITIALIZEBOXEDOBJECTFOR Double 278 | 279 | INITIALIZEBOXEDOBJECT(bool, Bool); 280 | INITIALIZEBOXEDOBJECT(char, Char); 281 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 282 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 283 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 284 | INITIALIZEBOXEDOBJECT(int16_t, Short); 285 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 286 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 287 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 288 | INITIALIZEBOXEDOBJECT(int64_t, Long); 289 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 290 | INITIALIZEBOXEDOBJECT(float, Float); 291 | INITIALIZEBOXEDOBJECT(double, Double); 292 | 293 | Reflection::ReflectionNonMemberMethodRegister RefString::s_BoxedObject_Constructor_nString_ = { AccessSpecifier::AccessSpecifier_public, "Constructor"_nv, static_cast(*)(nString)>(&RefString::Constructor) }; 294 | 295 | template <> 296 | nString Bool::_toString(const Bool* pThis) noexcept 297 | { 298 | return pThis->m_Obj ? "true"_nv : "false"_nv; 299 | } 300 | 301 | template <> 302 | nString Char::_toString(const Char* pThis) noexcept 303 | { 304 | return AnsiStringView{ pThis->m_Obj }; 305 | } 306 | 307 | template <> 308 | nString WChar::_toString(const WChar* pThis) noexcept 309 | { 310 | return WideStringView{ pThis->m_Obj }; 311 | } 312 | 313 | template <> 314 | nString SByte::_toString(const SByte* pThis) noexcept 315 | { 316 | const auto tmpStr{ toTString(pThis->m_Obj) }; 317 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 318 | } 319 | 320 | template <> 321 | nString Byte::_toString(const Byte* pThis) noexcept 322 | { 323 | const auto tmpStr{ toTString(pThis->m_Obj) }; 324 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 325 | } 326 | 327 | template <> 328 | nString Short::_toString(const Short* pThis) noexcept 329 | { 330 | const auto tmpStr{ toTString(pThis->m_Obj) }; 331 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 332 | } 333 | 334 | template <> 335 | nString UShort::_toString(const UShort* pThis) noexcept 336 | { 337 | const auto tmpStr{ toTString(pThis->m_Obj) }; 338 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 339 | } 340 | 341 | template <> 342 | nString Integer::_toString(const Integer* pThis) noexcept 343 | { 344 | const auto tmpStr{ toTString(pThis->m_Obj) }; 345 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 346 | } 347 | 348 | template <> 349 | nString UInteger::_toString(const UInteger* pThis) noexcept 350 | { 351 | const auto tmpStr{ toTString(pThis->m_Obj) }; 352 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 353 | } 354 | 355 | template <> 356 | nString Long::_toString(const Long* pThis) noexcept 357 | { 358 | const auto tmpStr{ toTString(pThis->m_Obj) }; 359 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 360 | } 361 | 362 | template <> 363 | nString ULong::_toString(const ULong* pThis) noexcept 364 | { 365 | const auto tmpStr{ toTString(pThis->m_Obj) }; 366 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 367 | } 368 | 369 | template <> 370 | nString Float::_toString(const Float* pThis) noexcept 371 | { 372 | const auto tmpStr{ toTString(pThis->m_Obj) }; 373 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 374 | } 375 | 376 | template <> 377 | nString Double::_toString(const Double* pThis) noexcept 378 | { 379 | const auto tmpStr{ toTString(pThis->m_Obj) }; 380 | return TStrView{ tmpStr.c_str(), tmpStr.size() }; 381 | } 382 | 383 | #undef INITIALIZEBOXEDOBJECT 384 | #define INITIALIZEBOXEDOBJECT(type, alias) RegisterType() 385 | 386 | Reflection::Reflection() 387 | { 388 | RegisterType(); 389 | RegisterType(); 390 | RegisterType()->UncheckedRegisterAttributes({ AttributeUsage{ AttributeTarget::Class } }); 391 | INITIALIZEBOXEDOBJECT(bool, Bool); 392 | INITIALIZEBOXEDOBJECT(char, Char); 393 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 394 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 395 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 396 | INITIALIZEBOXEDOBJECT(int16_t, Short); 397 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 398 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 399 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 400 | INITIALIZEBOXEDOBJECT(int64_t, Long); 401 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 402 | INITIALIZEBOXEDOBJECT(float, Float); 403 | INITIALIZEBOXEDOBJECT(double, Double); 404 | INITIALIZEBOXEDOBJECT(nString, RefString); 405 | INITIALIZEBOXEDOBJECT(void, Void); 406 | } 407 | 408 | Reflection::~Reflection() 409 | { 410 | } 411 | 412 | Object::~Object() 413 | { 414 | } 415 | 416 | natRefPointer Object::GetType() const noexcept 417 | { 418 | return typeof(Object); 419 | } 420 | 421 | nString Object::ToString() const noexcept 422 | { 423 | return GetType()->GetName(); 424 | } 425 | 426 | std::type_index Object::GetUnboxedType() 427 | { 428 | return GetType()->GetTypeIndex(); 429 | } 430 | 431 | natRefPointer Object::Box() 432 | { 433 | return make_ref>(); 434 | } 435 | -------------------------------------------------------------------------------- /Reflection/Method.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Interface.h" 3 | #include "Object.h" 4 | #include "Convert.h" 5 | #include "ArgumentPack.h" 6 | 7 | namespace rdetail_ 8 | { 9 | struct forward_call_t 10 | { 11 | constexpr forward_call_t() noexcept = default; 12 | }; 13 | 14 | constexpr forward_call_t forward_call; 15 | 16 | template 17 | struct InvokeNonMemberHelper 18 | { 19 | static natRefPointer Invoke(typename T::MethodType method, ArgumentPack const& pack) 20 | { 21 | return Object::Box(T::InvokeWithArgPack(method, pack)); 22 | } 23 | }; 24 | 25 | template 26 | struct InvokeNonMemberHelper::value>>> 27 | { 28 | static natRefPointer Invoke(typename T::MethodType method, ArgumentPack const& pack) 29 | { 30 | T::InvokeWithArgPack(method, pack); 31 | return Object::Box(); 32 | } 33 | }; 34 | 35 | template 36 | struct InvokeMemberHelper 37 | { 38 | static natRefPointer Invoke(natRefPointer object, typename T::MethodType method, ArgumentPack const& pack) 39 | { 40 | return Object::Box(T::InvokeWithArgPack(&object->Unbox(), method, pack)); 41 | } 42 | }; 43 | 44 | template 45 | struct InvokeMemberHelper::value>>> 46 | { 47 | static natRefPointer Invoke(natRefPointer object, typename T::MethodType method, ArgumentPack const& pack) 48 | { 49 | T::InvokeWithArgPack(&object->Unbox(), method, pack); 50 | return Object::Box(); 51 | } 52 | }; 53 | } 54 | 55 | template 56 | struct MethodHelper; 57 | 58 | template 59 | struct MethodHelper 60 | { 61 | typedef Ret(*MethodType)(Args...); 62 | typedef Ret ReturnType; 63 | 64 | static decltype(auto) InvokeWithArgs(MethodType method, Args... args) 65 | { 66 | return method(static_cast(args)...); 67 | } 68 | 69 | static decltype(auto) InvokeWithArgPack(MethodType method, ArgumentPack const& pack) 70 | { 71 | return InvokeWithArgPackHelper(method, pack, std::make_index_sequence{}); 72 | } 73 | 74 | static natRefPointer Invoke(MethodType method, ArgumentPack const& pack) 75 | { 76 | return rdetail_::InvokeNonMemberHelper::Invoke(method, pack); 77 | } 78 | 79 | static bool CompatWith(ArgumentPack const& pack) 80 | { 81 | return CompatWithImpl(pack, std::make_index_sequence{}); 82 | } 83 | 84 | static std::vector> GetType() 85 | { 86 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 87 | } 88 | 89 | private: 90 | template 91 | static decltype(auto) InvokeWithArgPackHelper(MethodType method, ArgumentPack const& pack, std::index_sequence) 92 | { 93 | return InvokeWithArgs(method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 94 | } 95 | 96 | template 97 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 98 | { 99 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 100 | } 101 | }; 102 | 103 | template 104 | struct MethodHelper&&)> 105 | { 106 | typedef Ret(*MethodType)(rdetail_::forward_call_t, std::tuple&&); 107 | typedef Ret ReturnType; 108 | 109 | static decltype(auto) InvokeWithArgs(MethodType method, Args... args) 110 | { 111 | return method(rdetail_::forward_call, std::forward_as_tuple(static_cast(args)...)); 112 | } 113 | 114 | static decltype(auto) InvokeWithArgPack(MethodType method, ArgumentPack const& pack) 115 | { 116 | return InvokeWithArgPackHelper(method, pack, std::make_index_sequence{}); 117 | } 118 | 119 | static natRefPointer Invoke(MethodType method, ArgumentPack const& pack) 120 | { 121 | return rdetail_::InvokeNonMemberHelper::Invoke(method, pack); 122 | } 123 | 124 | static bool CompatWith(ArgumentPack const& pack) 125 | { 126 | return CompatWithImpl(pack, std::make_index_sequence{}); 127 | } 128 | 129 | static std::vector> GetType() 130 | { 131 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 132 | } 133 | 134 | private: 135 | template 136 | static decltype(auto) InvokeWithArgPackHelper(MethodType method, ArgumentPack const& pack, std::index_sequence) 137 | { 138 | return InvokeWithArgs(method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 139 | } 140 | 141 | template 142 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 143 | { 144 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 145 | } 146 | }; 147 | 148 | template 149 | struct MethodHelper 150 | { 151 | typedef Ret(Class::*MethodType)(Args...); 152 | typedef Ret ReturnType; 153 | typedef Class ClassType; 154 | 155 | static decltype(auto) InvokeWithArgs(Class* object, MethodType method, Args... args) 156 | { 157 | return (object->*method)(static_cast(args)...); 158 | } 159 | 160 | static decltype(auto) InvokeWithArgPack(Class* object, MethodType method, ArgumentPack const& pack) 161 | { 162 | return InvokeWithArgPackHelper(object, method, pack, std::make_index_sequence{}); 163 | } 164 | 165 | static natRefPointer Invoke(natRefPointer object, MethodType method, ArgumentPack const& pack) 166 | { 167 | return rdetail_::InvokeMemberHelper::Invoke(object, method, pack); 168 | } 169 | 170 | static bool CompatWith(natRefPointer object, ArgumentPack const& pack) 171 | { 172 | return object->GetType()->GetTypeIndex() == typeid(Class) && CompatWithImpl(pack, std::make_index_sequence{}); 173 | } 174 | 175 | static std::vector> GetType() 176 | { 177 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 178 | } 179 | 180 | private: 181 | template 182 | static decltype(auto) InvokeWithArgPackHelper(Class* object, MethodType method, ArgumentPack const& pack, std::index_sequence) 183 | { 184 | return InvokeWithArgs(object, method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 185 | } 186 | 187 | template 188 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 189 | { 190 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 191 | } 192 | }; 193 | 194 | template 195 | struct MethodHelper&&)> 196 | { 197 | typedef Ret(Class::*MethodType)(rdetail_::forward_call_t, std::tuple&&); 198 | typedef Ret ReturnType; 199 | typedef Class ClassType; 200 | 201 | static decltype(auto) InvokeWithArgs(Class* object, MethodType method, Args... args) 202 | { 203 | return (object->*method)(rdetail_::forward_call, std::forward_as_tuple(static_cast(args)...)); 204 | } 205 | 206 | static decltype(auto) InvokeWithArgPack(Class* object, MethodType method, ArgumentPack const& pack) 207 | { 208 | return InvokeWithArgPackHelper(object, method, pack, std::make_index_sequence{}); 209 | } 210 | 211 | static natRefPointer Invoke(natRefPointer object, MethodType method, ArgumentPack const& pack) 212 | { 213 | return rdetail_::InvokeMemberHelper::Invoke(object, method, pack); 214 | } 215 | 216 | static bool CompatWith(natRefPointer object, ArgumentPack const& pack) 217 | { 218 | return object->GetType()->GetTypeIndex() == typeid(Class) && CompatWithImpl(pack, std::make_index_sequence{}); 219 | } 220 | 221 | static std::vector> GetType() 222 | { 223 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 224 | } 225 | 226 | private: 227 | template 228 | static decltype(auto) InvokeWithArgPackHelper(Class* object, MethodType method, ArgumentPack const& pack, std::index_sequence) 229 | { 230 | return InvokeWithArgs(object, method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 231 | } 232 | 233 | template 234 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 235 | { 236 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 237 | } 238 | }; 239 | 240 | template 241 | struct MethodHelper 242 | { 243 | typedef Ret(Class::*MethodType)(Args...) const; 244 | typedef Ret ReturnType; 245 | typedef Class ClassType; 246 | 247 | static decltype(auto) InvokeWithArgs(const Class* object, MethodType method, Args... args) 248 | { 249 | return (object->*method)(static_cast(args)...); 250 | } 251 | 252 | static decltype(auto) InvokeWithArgPack(const Class* object, MethodType method, ArgumentPack const& pack) 253 | { 254 | return InvokeWithArgPackHelper(object, method, pack, std::make_index_sequence{}); 255 | } 256 | 257 | static natRefPointer Invoke(natRefPointer object, MethodType method, ArgumentPack const& pack) 258 | { 259 | return rdetail_::InvokeMemberHelper::Invoke(object, method, pack); 260 | } 261 | 262 | static bool CompatWith(natRefPointer object, ArgumentPack const& pack) 263 | { 264 | return object->GetType()->GetTypeIndex() == typeid(Class) && CompatWithImpl(pack, std::make_index_sequence{}); 265 | } 266 | 267 | static std::vector> GetType() 268 | { 269 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 270 | } 271 | 272 | private: 273 | template 274 | static decltype(auto) InvokeWithArgPackHelper(const Class* object, MethodType method, ArgumentPack const& pack, std::index_sequence) 275 | { 276 | return InvokeWithArgs(object, method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 277 | } 278 | 279 | template 280 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 281 | { 282 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 283 | } 284 | }; 285 | 286 | template 287 | struct MethodHelper&&) const> 288 | { 289 | typedef Ret(Class::*MethodType)(rdetail_::forward_call_t, std::tuple&&) const; 290 | typedef Ret ReturnType; 291 | typedef Class ClassType; 292 | 293 | static decltype(auto) InvokeWithArgs(const Class* object, MethodType method, Args... args) 294 | { 295 | return (object->*method)(rdetail_::forward_call, std::forward_as_tuple(static_cast(args)...)); 296 | } 297 | 298 | static decltype(auto) InvokeWithArgPack(const Class* object, MethodType method, ArgumentPack const& pack) 299 | { 300 | return InvokeWithArgPackHelper(object, method, pack, std::make_index_sequence{}); 301 | } 302 | 303 | static natRefPointer Invoke(natRefPointer object, MethodType method, ArgumentPack const& pack) 304 | { 305 | return rdetail_::InvokeMemberHelper::Invoke(object, method, pack); 306 | } 307 | 308 | static bool CompatWith(natRefPointer object, ArgumentPack const& pack) 309 | { 310 | return object->GetType()->GetTypeIndex() == typeid(Class) && CompatWithImpl(pack, std::make_index_sequence{}); 311 | } 312 | 313 | static std::vector> GetType() 314 | { 315 | return{ Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType(), Reflection::GetInstance().GetType()... }; 316 | } 317 | 318 | private: 319 | template 320 | static decltype(auto) InvokeWithArgPackHelper(const Class* object, MethodType method, ArgumentPack const& pack, std::index_sequence) 321 | { 322 | return InvokeWithArgs(object, method, static_cast(Convert::ConvertTo>>(pack.Get(i))->Unbox>>())...); 323 | } 324 | 325 | template 326 | static bool CompatWithImpl(ArgumentPack const& pack, std::index_sequence) 327 | { 328 | return pack.Size() == sizeof...(i) && std::make_tuple((pack.GetType(i)->GetTypeIndex() == typeid(boxed_type_t))...) == std::make_tuple(std::bool_constant= 0>::value...); 329 | } 330 | }; 331 | 332 | template 333 | class NonMemberMethod; 334 | 335 | template 336 | class NonMemberMethod 337 | : public natRefObjImpl, IMethod> 338 | { 339 | public: 340 | typedef Ret(*MethodType)(Args...); 341 | 342 | NonMemberMethod(AccessSpecifier accessSpecifier, MethodType method) 343 | : m_AccessSpecifier{ accessSpecifier }, m_Func(method), m_Types(MethodHelper::GetType()) 344 | { 345 | } 346 | 347 | AccessSpecifier GetAccessSpecifier() const noexcept override 348 | { 349 | return m_AccessSpecifier; 350 | } 351 | 352 | AccessSpecifier SetAccessSpecifier(AccessSpecifier accessSpecifier) noexcept override 353 | { 354 | return std::exchange(m_AccessSpecifier, accessSpecifier); 355 | } 356 | 357 | natRefPointer Invoke(ArgumentPack const& pack) override 358 | { 359 | return MethodHelper::Invoke(m_Func, pack); 360 | } 361 | 362 | bool CompatWith(ArgumentPack const& pack) const noexcept override 363 | { 364 | return MethodHelper::CompatWith(pack); 365 | } 366 | 367 | natRefPointer GetReturnType() const noexcept override 368 | { 369 | return m_Types.front(); 370 | } 371 | 372 | size_t GetArgumentCount() const noexcept override 373 | { 374 | return m_Types.size() - 1; 375 | } 376 | 377 | natRefPointer GetArgumentType(size_t n) const noexcept override 378 | { 379 | return m_Types.at(n + 1); 380 | } 381 | 382 | MethodType Get() const noexcept 383 | { 384 | return m_Func; 385 | } 386 | 387 | private: 388 | AccessSpecifier m_AccessSpecifier; 389 | MethodType m_Func; 390 | std::vector> m_Types; 391 | }; 392 | 393 | template 394 | class MemberMethod; 395 | 396 | template 397 | class MemberMethod 398 | : public natRefObjImpl, IMemberMethod> 399 | { 400 | public: 401 | typedef Ret(Class::*MethodType)(Args...); 402 | 403 | MemberMethod(AccessSpecifier accessSpecifier, bool isVirtual, MethodType method) 404 | : m_AccessSpecifier{ accessSpecifier }, m_IsVirtual{ isVirtual }, m_Func(method), m_Types(MethodHelper::GetType()) 405 | { 406 | } 407 | 408 | AccessSpecifier GetAccessSpecifier() const noexcept override 409 | { 410 | return m_AccessSpecifier; 411 | } 412 | 413 | AccessSpecifier SetAccessSpecifier(AccessSpecifier accessSpecifier) noexcept override 414 | { 415 | return std::exchange(m_AccessSpecifier, accessSpecifier); 416 | } 417 | 418 | natRefPointer Invoke(natRefPointer object, ArgumentPack const& pack) override 419 | { 420 | if (object.Get() == nullptr) 421 | { 422 | nat_Throw(NullPointerException, "Object is nullptr."_nv); 423 | } 424 | 425 | return MethodHelper::Invoke(object, m_Func, pack); 426 | } 427 | 428 | bool CompatWith(natRefPointer object, ArgumentPack const& pack) const noexcept override 429 | { 430 | if (object.Get() == nullptr) 431 | { 432 | return false; 433 | } 434 | 435 | return MethodHelper::CompatWith(object, pack); 436 | } 437 | 438 | natRefPointer GetReturnType() const noexcept override 439 | { 440 | return m_Types.front(); 441 | } 442 | 443 | natRefPointer GetClassType() const noexcept override 444 | { 445 | return m_Types.at(1); 446 | } 447 | 448 | size_t GetArgumentCount() const noexcept override 449 | { 450 | return m_Types.size() - 2; 451 | } 452 | 453 | natRefPointer GetArgumentType(size_t n) const noexcept override 454 | { 455 | return m_Types.at(n + 2); 456 | } 457 | 458 | bool IsConstMemberMethod() const noexcept override 459 | { 460 | return false; 461 | } 462 | 463 | bool IsVirtual() const noexcept override 464 | { 465 | return m_IsVirtual; 466 | } 467 | 468 | MethodType Get() const noexcept 469 | { 470 | return m_Func; 471 | } 472 | 473 | private: 474 | AccessSpecifier m_AccessSpecifier; 475 | const bool m_IsVirtual; 476 | MethodType m_Func; 477 | std::vector> m_Types; 478 | }; 479 | 480 | template 481 | class MemberMethod 482 | : public natRefObjImpl, IMemberMethod> 483 | { 484 | public: 485 | typedef Ret(Class::*MethodType)(Args...) const; 486 | 487 | explicit MemberMethod(AccessSpecifier accessSpecifier, bool isVirtual, MethodType method) 488 | : m_AccessSpecifier{ accessSpecifier }, m_IsVirtual{ isVirtual }, m_Func(method), m_Types(MethodHelper::GetType()) 489 | { 490 | } 491 | 492 | AccessSpecifier GetAccessSpecifier() const noexcept override 493 | { 494 | return m_AccessSpecifier; 495 | } 496 | 497 | AccessSpecifier SetAccessSpecifier(AccessSpecifier accessSpecifier) noexcept override 498 | { 499 | return std::exchange(m_AccessSpecifier, accessSpecifier); 500 | } 501 | 502 | natRefPointer Invoke(natRefPointer object, ArgumentPack const& pack) override 503 | { 504 | return MethodHelper::Invoke(object, m_Func, pack); 505 | } 506 | 507 | bool CompatWith(natRefPointer object, ArgumentPack const& pack) const noexcept override 508 | { 509 | return MethodHelper::CompatWith(object, pack); 510 | } 511 | 512 | natRefPointer GetReturnType() const noexcept override 513 | { 514 | return m_Types.front(); 515 | } 516 | 517 | natRefPointer GetClassType() const noexcept override 518 | { 519 | return m_Types.at(1); 520 | } 521 | 522 | size_t GetArgumentCount() const noexcept override 523 | { 524 | return m_Types.size() - 2; 525 | } 526 | 527 | natRefPointer GetArgumentType(size_t n) const noexcept override 528 | { 529 | return m_Types.at(n + 2); 530 | } 531 | 532 | bool IsConstMemberMethod() const noexcept override 533 | { 534 | return true; 535 | } 536 | 537 | bool IsVirtual() const noexcept override 538 | { 539 | return m_IsVirtual; 540 | } 541 | 542 | MethodType Get() const noexcept 543 | { 544 | return m_Func; 545 | } 546 | 547 | private: 548 | AccessSpecifier m_AccessSpecifier; 549 | const bool m_IsVirtual; 550 | MethodType m_Func; 551 | std::vector> m_Types; 552 | }; 553 | -------------------------------------------------------------------------------- /Reflection/Reflection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Type.h" 10 | #include "Attribute.h" 11 | 12 | using namespace NatsuLib; 13 | 14 | #define GENERATE_METADATA_IMPL(classname) private: typedef classname Self_t_;\ 15 | public: static nStrView GetName() noexcept\ 16 | {\ 17 | return #classname##_nv;\ 18 | }\ 19 | natRefPointer GetType() const noexcept override\ 20 | {\ 21 | return typeof(Self_t_);\ 22 | } 23 | 24 | #define GENERATE_METADATA(classname, attributes) GENERATE_METADATA_IMPL(classname)\ 25 | private: static Reflection::ReflectionBaseClassesRegister _s_ReflectionHelper_##classname; 26 | 27 | #define GENERATE_METADATA_WITH_BASE_CLASSES(classname, attributes, ...) GENERATE_METADATA_IMPL(classname)\ 28 | private: static Reflection::ReflectionBaseClassesRegister _s_ReflectionHelper_##classname 29 | 30 | #define GENERATE_METADATA_DEFINITION(classname, attributes) Reflection::ReflectionBaseClassesRegister classname::_s_ReflectionHelper_##classname{ attributes } 31 | #define GENERATE_METADATA_DEFINITION_WITH_BASE_CLASSES(classname, attributes, ...) Reflection::ReflectionBaseClassesRegister classname::_s_ReflectionHelper_##classname{ attributes } 32 | 33 | #define DECLARE_REFLECTABLE_CLASS(classname) class classname : public Object 34 | #define DECLARE_REFLECTABLE_CLASS_WITH_BASE_CLASS(classname, baseclass) class classname : public std::enable_if_t::value, baseclass> 35 | #define DECLARE_REFLECTABLE_CLASS_WITH_BASE_CLASSES(classname, ...) struct classname : __VA_ARGS__ 36 | 37 | #define DECLARE_REFLECTABLE_INTERFACE(classname) struct classname : Object 38 | #define DECLARE_REFLECTABLE_INTERFACE_WITH_BASE_CLASS(classname, baseclass) struct classname : std::enable_if_t::value, baseclass> 39 | #define DECLARE_REFLECTABLE_INTERFACE_WITH_BASE_CLASSES(classname, ...) struct classname : __VA_ARGS__ 40 | 41 | #define DECLARE_NONMEMBER_METHOD(accessspecifier, classname, methodname, id, returntype, ...) private: static Reflection::ReflectionNonMemberMethodRegister _s_ReflectionHelper_##classname##_NonMemberMethod_##methodname##_##id##_;\ 42 | accessspecifier: static returntype methodname(__VA_ARGS__) 43 | 44 | #define DEFINE_NONMEMBER_METHOD(accessspecifier, classname, methodname, id, returntype, ...) Reflection::ReflectionNonMemberMethodRegister classname::_s_ReflectionHelper_##classname##_NonMemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, #methodname##_nv, static_cast(&classname::methodname) };\ 45 | returntype classname::methodname 46 | 47 | #define DECLARE_CONSTRUCTOR(accessspecifier, classname, specifiers, id, ...) private: static Reflection::ReflectionNonMemberMethodRegister _s_ReflectionHelper_##classname##_NonMemberMethod_##Constructor##_##id##_;\ 48 | static natRefPointer Constructor(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&);\ 49 | accessspecifier: specifiers classname(__VA_ARGS__) 50 | 51 | #define DEFINE_CONSTRUCTOR(accessspecifier, classname, specifiers, id, ...) Reflection::ReflectionNonMemberMethodRegister classname::_s_ReflectionHelper_##classname##_NonMemberMethod_##Constructor##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, "Constructor"_nv, static_cast(*)(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&)>(&classname::Constructor) };\ 52 | natRefPointer classname::Constructor(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&& args)\ 53 | {\ 54 | return ::CommonConstructor(std::move(args), typename std::make_index_sequence>::value>{});\ 55 | }\ 56 | classname::classname 57 | 58 | #define DECLARE_DEFAULT_COPYCONSTRUCTOR(accessspecifier, classname) DECLARE_CONSTRUCTOR(accessspecifier, classname, , CopyConstructor, classname const&) = default 59 | #define DEFINE_DEFAULT_COPYCONSTRUCTOR(accessspecifier, classname) Reflection::ReflectionNonMemberMethodRegister classname::_s_ReflectionHelper_##classname##_NonMemberMethod_##Constructor##_CopyConstructor##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, "Constructor"_nv, static_cast(*)(rdetail_::forward_call_t, std::tuple&&)>(&classname::Constructor) };\ 60 | natRefPointer classname::Constructor(rdetail_::forward_call_t, std::tuple&& args)\ 61 | {\ 62 | return ::CommonConstructor(std::move(args), typename std::make_index_sequence>::value>{});\ 63 | } 64 | 65 | #define DECLARE_DEFAULT_MOVECONSTRUCTOR(accessspecifier, classname) DECLARE_CONSTRUCTOR(accessspecifier, classname, , MoveConstructor, classname &&) = default 66 | #define DEFINE_DEFAULT_MOVECONSTRUCTOR(accessspecifier, classname) Reflection::ReflectionNonMemberMethodRegister classname::_s_ReflectionHelper_##classname##_NonMemberMethod_##Constructor##_MoveConstructor##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, "Constructor"_nv, static_cast(*)(rdetail_::forward_call_t, std::tuple&&)>(&classname::Constructor) };\ 67 | natRefPointer classname::Constructor(rdetail_::forward_call_t, std::tuple&& args)\ 68 | {\ 69 | return ::CommonConstructor(std::move(args), typename std::make_index_sequence>::value>{});\ 70 | } 71 | 72 | #define DECLARE_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_MemberMethod_##methodname##_##id##_;\ 73 | accessspecifier: specifiers returntype methodname(__VA_ARGS__) 74 | 75 | #define DEFINE_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, false, #methodname##_nv, static_cast(&classname::methodname) };\ 76 | returntype classname::methodname 77 | 78 | #define DECLARE_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_Const_MemberMethod_##methodname##_##id##_;\ 79 | accessspecifier: specifiers returntype methodname(__VA_ARGS__) const 80 | 81 | #define DEFINE_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_Const_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, false, #methodname##_nv, static_cast(&classname::methodname) };\ 82 | returntype classname::methodname 83 | 84 | #define DECLARE_VIRTUAL_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_Virtual_MemberMethod_##methodname##_##id##_;\ 85 | specifiers returntype methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&);\ 86 | template \ 87 | specifiers returntype methodname##_forwarder_impl_(std::tuple&& argTuple, std::index_sequence)\ 88 | {\ 89 | return methodname(std::forward(std::get(argTuple))...);\ 90 | }\ 91 | accessspecifier: virtual specifiers returntype methodname(__VA_ARGS__) 92 | 93 | #define DEFINE_VIRTUAL_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_Virtual_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, true, #methodname##_nv, static_cast&&)>(&classname::methodname##_forwarder_) };\ 94 | specifiers returntype classname::methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&& argTuple)\ 95 | {\ 96 | return methodname##_forwarder_impl_(std::move(argTuple), typename std::make_index_sequence>::value>{});\ 97 | }\ 98 | specifiers returntype classname::methodname 99 | 100 | #define DECLARE_PURE_VIRTUAL_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_PureVirtual_MemberMethod_##methodname##_##id##_;\ 101 | specifiers returntype methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&);\ 102 | template \ 103 | specifiers returntype methodname##_forwarder_impl_(std::tuple&& argTuple, std::index_sequence)\ 104 | {\ 105 | return methodname(std::forward(std::get(argTuple))...);\ 106 | }\ 107 | accessspecifier: virtual specifiers returntype methodname(__VA_ARGS__) = 0 108 | 109 | #define DEFINE_PURE_VIRTUAL_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_PureVirtual_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, true, #methodname##_nv, static_cast&&)>(&classname::methodname##_forwarder_) };\ 110 | specifiers returntype classname::methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&& argTuple)\ 111 | {\ 112 | return methodname##_forwarder_impl_(std::move(argTuple), typename std::make_index_sequence>::value>{});\ 113 | } 114 | 115 | #define DECLARE_VIRTUAL_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_Virtual_Const_MemberMethod_##methodname##_##id##_;\ 116 | specifiers returntype methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&) const;\ 117 | template \ 118 | specifiers returntype methodname##_forwarder_impl_(std::tuple&& argTuple, std::index_sequence) const\ 119 | {\ 120 | return methodname(std::forward(std::get(argTuple))...);\ 121 | }\ 122 | accessspecifier: virtual specifiers returntype methodname(__VA_ARGS__) const 123 | 124 | #define DEFINE_VIRTUAL_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_Virtual_Const_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, true, #methodname##_nv, static_cast&&) const>(&classname::methodname##_forwarder_) };\ 125 | specifiers returntype classname::methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&& argTuple) const\ 126 | {\ 127 | return methodname##_forwarder_impl_(std::move(argTuple), typename std::make_index_sequence>::value>{});\ 128 | }\ 129 | specifiers returntype classname::methodname 130 | 131 | #define DECLARE_PURE_VIRTUAL_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) private: static Reflection::ReflectionMemberMethodRegister _s_ReflectionHelper_##classname##_PureVirtual_Const_MemberMethod_##methodname##_##id##_;\ 132 | specifiers returntype methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&&);\ 133 | template \ 134 | specifiers returntype methodname##_forwarder_impl_(std::tuple&& argTuple, std::index_sequence)\ 135 | {\ 136 | return methodname(std::forward(std::get(argTuple))...);\ 137 | }\ 138 | accessspecifier: virtual specifiers returntype methodname(__VA_ARGS__) const = 0 139 | 140 | #define DEFINE_PURE_VIRTUAL_CONST_MEMBER_METHOD(accessspecifier, classname, specifiers, methodname, id, returntype, ...) Reflection::ReflectionMemberMethodRegister classname::_s_ReflectionHelper_##classname##_PureVirtual_Const_MemberMethod_##methodname##_##id##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, true, #methodname##_nv, static_cast&&)>(&classname::methodname##_forwarder_) };\ 141 | specifiers returntype classname::methodname##_forwarder_(rdetail_::forward_call_t, std::tuple<__VA_ARGS__>&& argTuple)\ 142 | {\ 143 | return methodname##_forwarder_impl_(std::move(argTuple), typename std::make_index_sequence>::value>{});\ 144 | } 145 | 146 | #define DECLARE_CONVERSION_OPERATOR(accessspecifier, classname, targettype) DECLARE_MEMBER_METHOD(accessspecifier, classname, , ConvertTo##targettype, , natRefPointer);\ 147 | accessspecifier: operator targettype() 148 | 149 | #define DEFINE_CONVERSION_OPERATOR(accessspecifier, classname, targettype) DEFINE_MEMBER_METHOD(accessspecifier, classname, , ConvertTo##targettype, , natRefPointer)(){ return this->operator targettype(); }\ 150 | classname::operator targettype() 151 | 152 | #define DECLARE_CONST_CONVERSION_OPERATOR(accessspecifier, classname, targettype) DECLARE_CONST_MEMBER_METHOD(accessspecifier, classname, , ConvertTo##targettype, , natRefPointer);\ 153 | accessspecifier: operator targettype() const 154 | 155 | #define DEFINE_CONST_CONVERSION_OPERATOR(accessspecifier, classname, targettype) DEFINE_CONST_MEMBER_METHOD(accessspecifier, classname, , ConvertTo##targettype, , natRefPointer)() const { return this->operator targettype(); }\ 156 | classname::operator targettype() const 157 | 158 | #define DECLARE_NONMEMBER_FIELD(accessspecifier, classname, fieldtype, fieldname) private: static Reflection::ReflectionNonMemberFieldRegister _s_ReflectionHelper_##classname##_NonMemberField_##fieldname##_;\ 159 | accessspecifier: static fieldtype fieldname 160 | 161 | #define DEFINE_NONMEMBER_FIELD(accessspecifier, classname, fieldtype, fieldname) Reflection::ReflectionNonMemberFieldRegister classname::_s_ReflectionHelper_##classname##_NonMemberField_##fieldname##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, #fieldname##_nv, &classname::fieldname };\ 162 | fieldtype classname::fieldname 163 | 164 | #define DECLARE_NONMEMBER_POINTER_FIELD(accessspecifier, classname, pointertotype, fieldname) private: static Reflection::ReflectionNonMemberFieldRegister _s_ReflectionHelper_##classname##_NonMemberPointerField_##fieldname##_;\ 165 | accessspecifier: static natRefPointer fieldname 166 | 167 | #define DEFINE_NONMEMBER_POINTER_FIELD(accessspecifier, classname, pointertotype, fieldname) Reflection::ReflectionNonMemberFieldRegister classname::_s_ReflectionHelper_##classname##_NonMemberPointerField_##fieldname##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, #fieldname##_nv, &classname::fieldname };\ 168 | natRefPointer classname::fieldname 169 | 170 | #define DECLARE_MEMBER_FIELD(accessspecifier, classname, fieldtype, fieldname) private: static Reflection::ReflectionMemberFieldRegister _s_ReflectionHelper_##classname##_MemberField_##fieldname##_;\ 171 | accessspecifier: fieldtype fieldname 172 | 173 | #define DEFINE_MEMBER_FIELD(accessspecifier, classname, fieldtype, fieldname) Reflection::ReflectionMemberFieldRegister classname::_s_ReflectionHelper_##classname##_MemberField_##fieldname##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, #fieldname##_nv, &classname::fieldname } 174 | 175 | #define DECLARE_MEMBER_POINTER_FIELD(accessspecifier, classname, pointertotype, fieldname) private: static Reflection::ReflectionMemberFieldRegister _s_ReflectionHelper_##classname##_MemberPointerField_##fieldname##_;\ 176 | accessspecifier: natRefPointer fieldname 177 | 178 | #define DEFINE_MEMBER_POINTER_FIELD(accessspecifier, classname, pointertotype, fieldname) Reflection::ReflectionMemberFieldRegister classname::_s_ReflectionHelper_##classname##_MemberPointerField_##fieldname##_{ AccessSpecifier::AccessSpecifier_##accessspecifier, #fieldname##_nv, &classname::fieldname } 179 | 180 | #define typeof(type) Reflection::GetInstance().GetType() 181 | #define typeofexp(expression) Reflection::GetInstance().GetType() 182 | #define typeofname(name) Reflection::GetInstance().GetType(name) 183 | 184 | #define nameof_(name) #name##_nv 185 | #define nameof(name) ((static_cast(name), nameof_(name))) 186 | 187 | namespace rdetail_ 188 | { 189 | template 190 | struct ExplicitRegisterClass; 191 | 192 | template 193 | struct ExplicitRegisterClass 194 | { 195 | static void Execute(); 196 | }; 197 | 198 | template <> 199 | struct ExplicitRegisterClass<> 200 | { 201 | static void Execute() 202 | { 203 | } 204 | }; 205 | } 206 | 207 | class Reflection 208 | : nonmovable 209 | { 210 | public: 211 | template 212 | struct ReflectionClassRegister 213 | { 214 | explicit ReflectionClassRegister(AttributeSet&& attributes) 215 | { 216 | GetInstance().RegisterType()->RegisterAttributes(std::move(attributes)); 217 | } 218 | }; 219 | 220 | template 221 | struct ReflectionBaseClassesRegister 222 | { 223 | explicit ReflectionBaseClassesRegister(AttributeSet&& attributes) 224 | { 225 | rdetail_::ExplicitRegisterClass::Execute(); 226 | GetInstance().RegisterAttributes(std::move(attributes)); 227 | GetInstance().RegisterBaseClasses(); 228 | } 229 | }; 230 | 231 | template 232 | struct ReflectionNonMemberMethodRegister 233 | { 234 | template 235 | ReflectionNonMemberMethodRegister(AccessSpecifier accessSpecifier, nStrView name, Func method) 236 | { 237 | GetInstance().RegisterNonMemberMethod(accessSpecifier, name, method); 238 | } 239 | }; 240 | 241 | template 242 | struct ReflectionMemberMethodRegister 243 | { 244 | template 245 | ReflectionMemberMethodRegister(AccessSpecifier accessSpecifier, bool isVirtual, nStrView name, Func method) 246 | { 247 | GetInstance().RegisterMemberMethod(accessSpecifier, isVirtual, name, method); 248 | } 249 | }; 250 | 251 | template 252 | struct ReflectionNonMemberFieldRegister 253 | { 254 | template 255 | ReflectionNonMemberFieldRegister(AccessSpecifier accessSpecifier, nStrView name, U field) 256 | { 257 | GetInstance().RegisterNonMemberField(accessSpecifier, name, field); 258 | } 259 | }; 260 | 261 | template 262 | struct ReflectionMemberFieldRegister 263 | { 264 | template 265 | ReflectionMemberFieldRegister(AccessSpecifier accessSpecifier, nStrView name, U field) 266 | { 267 | GetInstance().RegisterMemberField(accessSpecifier, name, field); 268 | } 269 | }; 270 | 271 | static Reflection& GetInstance(); 272 | 273 | template 274 | natRefPointer> RegisterType() 275 | { 276 | auto iter = m_TypeTable.find(typeid(Class)); 277 | if (iter == m_TypeTable.end()) 278 | { 279 | auto type = make_ref>(); 280 | m_TypeTable.emplace(typeid(Class), type); 281 | return type; 282 | } 283 | return iter->second; 284 | } 285 | 286 | template 287 | void RegisterAttributes(AttributeSet&& attributes) 288 | { 289 | GetType()->RegisterAttributes(std::move(attributes)); 290 | } 291 | 292 | template 293 | void RegisterBaseClasses() 294 | { 295 | GetType()->RegisterBaseClasses({ GetType()... }); 296 | } 297 | 298 | template 299 | void RegisterNonMemberMethod(AccessSpecifier accessSpecifier, nStrView name, Func method); 300 | 301 | template 302 | void RegisterMemberMethod(AccessSpecifier accessSpecifier, bool isVirtual, nStrView name, Func method); 303 | 304 | template 305 | void RegisterNonMemberField(AccessSpecifier accessSpecifier, nStrView name, Field field); 306 | 307 | template 308 | void RegisterMemberField(AccessSpecifier accessSpecifier, nStrView name, Field field); 309 | 310 | template 311 | natRefPointer GetType(); 312 | 313 | natRefPointer GetType(nStrView typeName); 314 | 315 | Linq> GetTypes() const; 316 | 317 | private: 318 | Reflection(); 319 | ~Reflection(); 320 | 321 | std::unordered_map> m_TypeTable; 322 | }; 323 | 324 | namespace rdetail_ 325 | { 326 | template 327 | struct RegisterHelper 328 | { 329 | static void Do() 330 | { 331 | } 332 | }; 333 | 334 | template 335 | struct RegisterHelper::value>>> 336 | { 337 | static void Do() 338 | { 339 | Reflection::GetInstance().RegisterType(); 340 | } 341 | }; 342 | } 343 | 344 | template 345 | void rdetail_::ExplicitRegisterClass::Execute() 346 | { 347 | RegisterHelper::Do(); 348 | ExplicitRegisterClass::Execute(); 349 | } 350 | 351 | #include "Object.h" 352 | 353 | template 354 | struct should_box 355 | : std::false_type 356 | { 357 | }; 358 | 359 | template 360 | struct should_box::value>>> 361 | : std::true_type 362 | { 363 | }; 364 | 365 | // 若需要将并非派生于Object的类型作为可反射对象使用(例如函数的参数或返回值等),需要在此对BoxedObject特化此类型 366 | // 注意你仍然需要手动或者利用宏来注册 367 | // BoxedObject必须继承于Object且GetObj方法返回第一个模板参数的类型的左值引用 368 | template 369 | class BoxedObject final 370 | : public Object 371 | { 372 | public: 373 | [[noreturn]] T& GetObj() 374 | { 375 | nat_Throw(ReflectionException, "Cannot get object."_nv); 376 | } 377 | }; 378 | 379 | #undef INITIALIZEBOXEDOBJECT 380 | #define INITIALIZEBOXEDOBJECT(type, alias) private: static Reflection::ReflectionNonMemberMethodRegister s_BoxedObject_Constructor_##type##_;\ 381 | public: BoxedObject(type value) : m_Obj { static_cast(value) } {}\ 382 | static natRefPointer Constructor(type value) { return make_ref(std::move(value)); } 383 | 384 | #pragma warning (push) 385 | #pragma warning (disable : 4800) 386 | 387 | template 388 | class BoxedObject>::value>>> final 389 | : public Object 390 | { 391 | public: 392 | typedef BoxedObject Self_t_; 393 | typedef T UnderlyingType; 394 | static nStrView GetName() noexcept; 395 | natRefPointer GetType() const noexcept override 396 | { 397 | return typeof(Self_t_); 398 | } 399 | 400 | BoxedObject() 401 | : m_Obj{} 402 | { 403 | } 404 | 405 | INITIALIZEBOXEDOBJECT(bool, Bool); 406 | INITIALIZEBOXEDOBJECT(char, Char); 407 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 408 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 409 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 410 | INITIALIZEBOXEDOBJECT(int16_t, Short); 411 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 412 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 413 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 414 | INITIALIZEBOXEDOBJECT(int64_t, Long); 415 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 416 | INITIALIZEBOXEDOBJECT(float, Float); 417 | INITIALIZEBOXEDOBJECT(double, Double); 418 | 419 | operator T() const noexcept 420 | { 421 | return m_Obj; 422 | } 423 | 424 | operator T&() noexcept 425 | { 426 | return m_Obj; 427 | } 428 | 429 | operator T const&() const noexcept 430 | { 431 | return m_Obj; 432 | } 433 | 434 | T& GetObj() noexcept 435 | { 436 | return m_Obj; 437 | } 438 | 439 | nString ToString() const noexcept override 440 | { 441 | return _toString(this); 442 | } 443 | 444 | std::type_index GetUnboxedType() override 445 | { 446 | return typeid(T); 447 | } 448 | 449 | private: 450 | static nString _toString(const BoxedObject* pThis) noexcept; 451 | 452 | T m_Obj; 453 | }; 454 | 455 | #pragma warning (pop) 456 | 457 | template <> 458 | class BoxedObject final 459 | : public Object 460 | { 461 | public: 462 | typedef BoxedObject Self_t_; 463 | typedef nString UnderlyingType; 464 | 465 | static nStrView GetName() noexcept 466 | { 467 | return "RefString"_nv; 468 | } 469 | 470 | natRefPointer GetType() const noexcept override 471 | { 472 | return typeof(BoxedObject); 473 | } 474 | 475 | BoxedObject() 476 | : m_Obj{} 477 | { 478 | } 479 | 480 | INITIALIZEBOXEDOBJECT(nString, RefString); 481 | 482 | operator nString() const noexcept 483 | { 484 | return m_Obj; 485 | } 486 | 487 | operator nString&() noexcept 488 | { 489 | return m_Obj; 490 | } 491 | 492 | operator nString const&() const noexcept 493 | { 494 | return m_Obj; 495 | } 496 | 497 | nString& GetObj() noexcept 498 | { 499 | return m_Obj; 500 | } 501 | 502 | nString ToString() const noexcept override 503 | { 504 | return m_Obj; 505 | } 506 | 507 | std::type_index GetUnboxedType() override 508 | { 509 | return typeid(nString); 510 | } 511 | 512 | private: 513 | nString m_Obj; 514 | }; 515 | 516 | template <> 517 | class BoxedObject final 518 | : public Object 519 | { 520 | public: 521 | typedef BoxedObject Self_t_; 522 | static nStrView GetName() noexcept; 523 | natRefPointer GetType() const noexcept override 524 | { 525 | return Reflection::GetInstance().GetType(); 526 | } 527 | 528 | nString ToString() const noexcept override 529 | { 530 | return "void"_nv; 531 | } 532 | 533 | std::type_index GetUnboxedType() override 534 | { 535 | return typeid(void); 536 | } 537 | 538 | [[noreturn]] void GetObj() 539 | { 540 | nat_Throw(ReflectionException, "Cannot get object."_nv); 541 | } 542 | }; 543 | 544 | #undef INITIALIZEBOXEDOBJECT 545 | #define INITIALIZEBOXEDOBJECT(type, alias) template <> inline nStrView BoxedObject::GetName() noexcept\ 546 | {\ 547 | /*return "BoxedObject<"## #type ##">"_nv;*/\ 548 | return #alias##_nv;\ 549 | } 550 | 551 | INITIALIZEBOXEDOBJECT(bool, Bool); 552 | INITIALIZEBOXEDOBJECT(char, Char); 553 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 554 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 555 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 556 | INITIALIZEBOXEDOBJECT(int16_t, Short); 557 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 558 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 559 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 560 | INITIALIZEBOXEDOBJECT(int64_t, Long); 561 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 562 | INITIALIZEBOXEDOBJECT(float, Float); 563 | INITIALIZEBOXEDOBJECT(double, Double); 564 | 565 | inline nStrView BoxedObject::GetName() noexcept 566 | { 567 | return "Void"_nv; 568 | } 569 | 570 | template 571 | std::enable_if_t::value, bool> operator==(natRefPointer const& ptr, nullptr_t) 572 | { 573 | return ptr->GetType()->GetTypeIndex() == typeid(BoxedObject) || ptr.Get() == nullptr; 574 | } 575 | 576 | template 577 | std::enable_if_t::value, bool> operator==(nullptr_t, natRefPointer const& ptr) 578 | { 579 | return ptr == nullptr; 580 | } 581 | 582 | template 583 | void Type::RegisterBaseClasses(std::initializer_list> baseClasses) 584 | { 585 | m_BaseClasses.assign(baseClasses); 586 | } 587 | 588 | #undef INITIALIZEBOXEDOBJECT 589 | #define INITIALIZEBOXEDOBJECT(type, alias) typedef BoxedObject alias 590 | 591 | INITIALIZEBOXEDOBJECT(bool, Bool); 592 | INITIALIZEBOXEDOBJECT(char, Char); 593 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 594 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 595 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 596 | INITIALIZEBOXEDOBJECT(int16_t, Short); 597 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 598 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 599 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 600 | INITIALIZEBOXEDOBJECT(int64_t, Long); 601 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 602 | INITIALIZEBOXEDOBJECT(float, Float); 603 | INITIALIZEBOXEDOBJECT(double, Double); 604 | INITIALIZEBOXEDOBJECT(nString, RefString); 605 | INITIALIZEBOXEDOBJECT(void, Void); 606 | 607 | #undef INITIALIZEBOXEDOBJECT 608 | #define INITIALIZEBOXEDOBJECT(type, alias) extern template class BoxedObject 609 | 610 | INITIALIZEBOXEDOBJECT(bool, Bool); 611 | INITIALIZEBOXEDOBJECT(char, Char); 612 | INITIALIZEBOXEDOBJECT(wchar_t, WChar); 613 | INITIALIZEBOXEDOBJECT(int8_t, SByte); 614 | INITIALIZEBOXEDOBJECT(uint8_t, Byte); 615 | INITIALIZEBOXEDOBJECT(int16_t, Short); 616 | INITIALIZEBOXEDOBJECT(uint16_t, UShort); 617 | INITIALIZEBOXEDOBJECT(int32_t, Integer); 618 | INITIALIZEBOXEDOBJECT(uint32_t, UInteger); 619 | INITIALIZEBOXEDOBJECT(int64_t, Long); 620 | INITIALIZEBOXEDOBJECT(uint64_t, ULong); 621 | INITIALIZEBOXEDOBJECT(float, Float); 622 | INITIALIZEBOXEDOBJECT(double, Double); 623 | INITIALIZEBOXEDOBJECT(nString, RefString); 624 | INITIALIZEBOXEDOBJECT(void, Void); 625 | 626 | template 627 | std::enable_if_t::value, natRefPointer> Object::Box(natRefPointer const& ptr) 628 | { 629 | return make_ref>(ptr); 630 | } 631 | 632 | template 633 | std::enable_if_t::value, natRefPointer> Object::Box(T obj) 634 | { 635 | return make_ref>(std::move(obj)); 636 | } 637 | 638 | namespace rdetail_ 639 | { 640 | template 641 | struct boxed_type_impl_ 642 | { 643 | typedef T type; 644 | }; 645 | 646 | template 647 | struct boxed_type_impl_ 648 | { 649 | typedef BoxedObject type; 650 | }; 651 | 652 | template 653 | struct boxed_type_impl 654 | : boxed_type_impl_::value> 655 | { 656 | }; 657 | 658 | template 659 | struct boxed_type_impl> 660 | : boxed_type_impl 661 | { 662 | }; 663 | } 664 | 665 | template 666 | struct boxed_type 667 | : rdetail_::boxed_type_impl>> 668 | { 669 | }; 670 | 671 | template 672 | using boxed_type_t = typename boxed_type::type; 673 | 674 | template 675 | struct is_boxed 676 | : std::false_type 677 | { 678 | }; 679 | 680 | template 681 | struct is_boxed> 682 | : std::true_type 683 | { 684 | }; 685 | 686 | template 687 | bool Type::IsBoxed() const noexcept 688 | { 689 | return is_boxed::value; 690 | } 691 | 692 | template 693 | T& Object::Unbox() 694 | { 695 | auto type = GetType(); 696 | auto typeindex = type->GetTypeIndex(); 697 | if (typeindex == typeid(BoxedObject)) 698 | { 699 | nat_Throw(ReflectionException, "Cannot unbox a void object."_nv); 700 | } 701 | if (typeindex == typeid(T)) 702 | { 703 | auto pRet = natUtil::Expect::Get(this); 704 | if (pRet) 705 | { 706 | return *pRet; 707 | } 708 | 709 | nat_Throw(ReflectionException, "Type wrong."_nv); 710 | } 711 | if (typeindex == typeid(BoxedObject)) 712 | { 713 | return static_cast*>(this)->GetObj(); 714 | } 715 | // 开销巨大所以留在最后判断 716 | auto Ttype = typeof(boxed_type_t); 717 | if (type->IsExtendFrom(Ttype) || Ttype->IsExtendFrom(type)) 718 | { 719 | auto pRet = natUtil::Expect::Get(this); 720 | if (pRet) 721 | { 722 | return *pRet; 723 | } 724 | } 725 | 726 | nat_Throw(ReflectionException, "Type wrong."_nv); 727 | } 728 | 729 | template 730 | natRefPointer Reflection::GetType() 731 | { 732 | auto iter = m_TypeTable.find(typeid(boxed_type_t)); 733 | if (iter != m_TypeTable.end()) 734 | { 735 | return iter->second; 736 | } 737 | 738 | nat_Throw(ReflectionException, "Type not found."_nv); 739 | } 740 | 741 | // 要求这个类型可以被实例化以及移动构造,如果你的类型不符合这个要求,你需要自行特化 742 | #define REGISTER_BOXED_OBJECT(type) template <>\ 743 | class BoxedObject final : public Object\ 744 | {\ 745 | public:\ 746 | static nStrView GetName() noexcept { return #type##_nv; }\ 747 | natRefPointer GetType() const noexcept override { return typeof(BoxedObject); }\ 748 | std::type_index GetUnboxedType() override { return typeid(type); }\ 749 | BoxedObject(type&& value) : m_Obj(std::move(value)) {}\ 750 | operator type&() { return m_Obj; }\ 751 | type& GetObj() noexcept { return m_Obj; }\ 752 | private:\ 753 | static Reflection::ReflectionBaseClassesRegister _s_ReflectionHelper_BoxedObject;\ 754 | static Reflection::ReflectionNonMemberMethodRegister _s_ReflectionHelper_BoxedObject_Constructor;\ 755 | static natRefPointer Constructor(type&& value) { return make_ref>(std::move(value)); }\ 756 | type m_Obj;\ 757 | } 758 | 759 | #define REGISTER_BOXED_OBJECT_DEF(type) Reflection::ReflectionBaseClassesRegister, Object> BoxedObject::_s_ReflectionHelper_BoxedObject { WITH() };\ 760 | Reflection::ReflectionNonMemberMethodRegister> BoxedObject::_s_ReflectionHelper_BoxedObject_Constructor { AccessSpecifier::AccessSpecifier_public, "Constructor"_nv, static_cast(*)(type&&)>(&BoxedObject::Constructor) } 761 | 762 | #define REGISTER_BOXED_REFOBJECT(type) template <>\ 763 | class BoxedObject final : public Object\ 764 | {\ 765 | public:\ 766 | static nStrView GetName() noexcept { return #type##_nv; }\ 767 | natRefPointer GetType() const noexcept override { return typeof(BoxedObject); }\ 768 | std::type_index GetUnboxedType() override { return typeid(type); }\ 769 | BoxedObject(natRefPointer value) : m_Obj(std::move(value)) {}\ 770 | BoxedObject(BoxedObject const& other) = default;\ 771 | BoxedObject(BoxedObject&& other) noexcept = default;\ 772 | operator type&() { return *m_Obj; }\ 773 | type& GetObj() noexcept { return *m_Obj; }\ 774 | private:\ 775 | static Reflection::ReflectionBaseClassesRegister _s_ReflectionHelper_BoxedObject;\ 776 | static Reflection::ReflectionNonMemberMethodRegister _s_ReflectionHelper_BoxedObject_CopyConstructor;\ 777 | static Reflection::ReflectionNonMemberMethodRegister _s_ReflectionHelper_BoxedObject_MoveConstructor;\ 778 | static natRefPointer Constructor(BoxedObject const& other) { return make_ref>(other); }\ 779 | static natRefPointer Constructor(BoxedObject&& other) { return make_ref>(std::move(other)); }\ 780 | natRefPointer m_Obj;\ 781 | } 782 | 783 | #define REGISTER_BOXED_REFOBJECT_DEF(type) Reflection::ReflectionBaseClassesRegister, Object> BoxedObject::_s_ReflectionHelper_BoxedObject { WITH() };\ 784 | Reflection::ReflectionNonMemberMethodRegister> BoxedObject::_s_ReflectionHelper_BoxedObject_CopyConstructor { AccessSpecifier::AccessSpecifier_public, "Constructor"_nv, static_cast(*)(BoxedObject const&)>(&BoxedObject::Constructor) };\ 785 | Reflection::ReflectionNonMemberMethodRegister> BoxedObject::_s_ReflectionHelper_BoxedObject_MoveConstructor { AccessSpecifier::AccessSpecifier_public, "Constructor"_nv, static_cast(*)(BoxedObject&&)>(&BoxedObject::Constructor) } 786 | 787 | #include "Field.h" 788 | 789 | template 790 | natRefPointer MemberField::GetType() 791 | { 792 | return Reflection::GetInstance().GetType>(); 793 | } 794 | 795 | template 796 | void Reflection::RegisterNonMemberField(AccessSpecifier accessSpecifier, nStrView name, Field field) 797 | { 798 | GetType()->RegisterNonMemberField(name, make_ref>(accessSpecifier, field)); 799 | } 800 | 801 | template 802 | void Reflection::RegisterMemberField(AccessSpecifier accessSpecifier, nStrView name, Field field) 803 | { 804 | GetType()->RegisterMemberField(name, make_ref>(accessSpecifier, field)); 805 | } 806 | 807 | #include "Method.h" 808 | 809 | template 810 | void Reflection::RegisterNonMemberMethod(AccessSpecifier accessSpecifier, nStrView name, Func method) 811 | { 812 | GetType()->RegisterNonMemberMethod(name, make_ref>(accessSpecifier, method)); 813 | } 814 | 815 | template 816 | void Reflection::RegisterMemberMethod(AccessSpecifier accessSpecifier, bool isVirtual, nStrView name, Func method) 817 | { 818 | GetType()->RegisterMemberMethod(name, make_ref>(accessSpecifier, isVirtual, method)); 819 | } 820 | 821 | #include "Convert.h" 822 | #include "ArgumentPack.h" 823 | 824 | inline natRefPointer Convert::ConvertTo(natRefPointer obj, natRefPointer toType) 825 | { 826 | if (obj->GetType()->Equal(toType.Get())) 827 | { 828 | return obj; 829 | } 830 | 831 | return toType->Construct({ obj }); 832 | } 833 | 834 | template 835 | natRefPointer Convert::ConvertTo(natRefPointer obj) 836 | { 837 | return ConvertTo(obj, typeof(T)); 838 | } 839 | --------------------------------------------------------------------------------