├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CleanSolution.ps1 ├── Directory.Build.props ├── ImmediateReflection.sln ├── ImmediateReflection.sln.DotSettings ├── ImmediateReflection.snk ├── LICENSE ├── README.md ├── RELEASE_NOTES.md ├── SonarQube.Analysis.xml ├── appveyor.yml ├── benchmarks ├── Directory.Build.props └── ImmediateReflection.Benchmark │ ├── Attributes │ └── TestAttributes.cs │ ├── Benchmark.cs │ ├── BenchmarkBase.cs │ ├── Benchmarks │ ├── CopyConstructorBenchmark.cs │ ├── DefaultConstructorBenchmark.cs │ ├── FieldGetterBenchmark.cs │ ├── FieldMultiGetterBenchmark.cs │ ├── FieldMultiSetterBenchmark.cs │ ├── FieldSetterBenchmark.cs │ ├── GetAttributesBenchmark.cs │ ├── MultiCopyConstructorBenchmark.cs │ ├── MultiDefaultConstructorBenchmark.cs │ ├── PropertyGetterBenchmark.cs │ ├── PropertyGetterOverObjectsBenchmark.cs │ ├── PropertyMultiGetterBenchmark.cs │ ├── PropertyMultiSetterBenchmark.cs │ ├── PropertySetterBenchmark.cs │ └── PropertySetterOverObjectsBenchmark.cs │ ├── Helpers │ └── ExpressionsHelpers.cs │ ├── ImmediateReflection.Benchmark.csproj │ ├── Objects │ ├── AttributesBenchmarkObject.cs │ ├── BenchmarkObject.cs │ ├── BenchmarkObject2.cs │ ├── BenchmarkObject3.cs │ ├── BenchmarkObject4.cs │ ├── CopyableBenchmarkObject.cs │ ├── CopyableBenchmarkObject2.cs │ ├── CopyableBenchmarkObject3.cs │ └── CopyableBenchmarkObject4.cs │ └── ObjectsBenchmarkBase.cs ├── build ├── BuildSetup.props ├── releaseDoc.ps1 ├── serveDoc.ps1 └── setupBuild.ps1 ├── docs ├── .gitignore ├── api │ ├── .gitignore │ └── index.md ├── docfx.json ├── documentation │ ├── benchmarks.md │ ├── benchmarks │ │ ├── attributes_benchmarks.md │ │ ├── copy_constructor_benchmarks.md │ │ ├── default_constructor_benchmarks.md │ │ ├── get_set_benchmarks.md │ │ ├── get_set_multiple_objects_benchmarks.md │ │ ├── multiple_get_set_benchmarks.md │ │ └── toc.yml │ ├── general-coding-guidelines.md │ ├── getting-started.md │ ├── guidelines │ │ ├── csharp-best-practices.md │ │ ├── csharp-coding-guidelines.md │ │ └── toc.yml │ ├── toc.yml │ └── tutorials │ │ ├── immediate-field.md │ │ ├── immediate-member.md │ │ ├── immediate-property.md │ │ ├── immediate-type.md │ │ ├── object-wrapper.md │ │ ├── open-delegates.md │ │ └── toc.yml ├── images │ ├── check.svg │ ├── cross.svg │ ├── favicon.ico │ ├── immediate_reflection_logo.png │ └── logo.svg ├── index.md ├── templates │ └── material │ │ ├── partials │ │ └── head.tmpl.partial │ │ └── styles │ │ └── main.css └── toc.yml ├── src ├── Directory.Build.props ├── ImmediateReflection.CommonInternals │ ├── Externs │ │ └── JetBrains.Annotations.cs │ ├── ImmediateReflection.CommonInternals.projitems │ ├── ImmediateReflection.CommonInternals.shproj │ └── Signing │ │ └── PublicKey.cs ├── ImmediateReflection │ ├── Cache │ │ ├── AttributesCache.cs │ │ ├── CachesHandler.cs │ │ ├── ConstructorData.cs │ │ └── MemoryCache.cs │ ├── Delegates │ │ ├── Delegates.cs │ │ └── DelegatesFactory.cs │ ├── Extensions │ │ ├── ImmediateAttributesExtensions.cs │ │ ├── ImmediateMemberExtensions.cs │ │ ├── ImmediateReflectionExtensions.cs │ │ ├── MemberExtensions.cs │ │ ├── ObjectExtensions.cs │ │ └── TypeExtensions.cs │ ├── Helpers │ │ ├── FieldHelpers.cs │ │ └── ReflectionHelpers.cs │ ├── ImmediateField.cs │ ├── ImmediateFields.cs │ ├── ImmediateMember.cs │ ├── ImmediateProperties.cs │ ├── ImmediateProperty.cs │ ├── ImmediateReflection.csproj │ ├── ImmediateType.cs │ ├── ObjectWrapper.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── TypeAccessor.cs └── PackagesGeneration.props └── tests ├── Directory.Build.props └── ImmediateReflection.Tests ├── ConstructorTestHelpers.cs ├── Delegates └── DelegatesFactoryTests.cs ├── Extensions ├── ImmediateAttributesExtensionsTests.cs ├── ImmediateMemberExtensionsTests.cs ├── ImmediateReflectionExtensionsTests.cs ├── MemberExtensionsTests.cs ├── ObjectExtensionsTests.cs └── TypeExtensionsTests.cs ├── ImmediateAttributesTestsBase.cs ├── ImmediateFieldTests.cs ├── ImmediateFieldsTests.cs ├── ImmediateMemberTests.cs ├── ImmediatePropertiesTests.cs ├── ImmediatePropertyTests.cs ├── ImmediateReflection.Tests.csproj ├── ImmediateReflectionTestsBase.cs ├── ImmediateTypeTests.cs ├── ObjectWrapperTests.cs ├── Serialization └── SerializationTests.cs ├── TestTypes.cs └── TypeAccessorTests.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | # To learn more about .editorconfig see https://aka.ms/editorconfigdocs 2 | 3 | ############################### 4 | # Core EditorConfig Options # 5 | ############################### 6 | root = true 7 | # All files 8 | [*] 9 | indent_style = space 10 | # Code files 11 | [*.{h,hpp,inl,c,cpp,cs,csx,vb,vbx}] 12 | indent_size = 4 13 | trim_trailing_whitespace = true 14 | insert_final_newline = false 15 | charset = utf-8-bom 16 | 17 | ############################### 18 | # .NET Coding Conventions # 19 | ############################### 20 | [*.{cs,vb}] 21 | # Organize usings 22 | dotnet_sort_system_directives_first = true 23 | # this. preferences 24 | dotnet_style_qualification_for_field = false:silent 25 | dotnet_style_qualification_for_property = false:silent 26 | dotnet_style_qualification_for_method = false:silent 27 | dotnet_style_qualification_for_event = false:silent 28 | # Language keywords vs BCL types preferences 29 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent 30 | dotnet_style_predefined_type_for_member_access = true:silent 31 | # Parentheses preferences 32 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent 33 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent 34 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent 35 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent 36 | # Modifier preferences 37 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent 38 | dotnet_style_readonly_field = true:suggestion 39 | # Expression-level preferences 40 | dotnet_style_object_initializer = true:suggestion 41 | dotnet_style_collection_initializer = true:suggestion 42 | dotnet_style_explicit_tuple_names = true:suggestion 43 | dotnet_style_null_propagation = true:suggestion 44 | dotnet_style_coalesce_expression = true:suggestion 45 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent 46 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 47 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 48 | dotnet_style_prefer_auto_properties = true:silent 49 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent 50 | dotnet_style_prefer_conditional_expression_over_return = true:silent 51 | 52 | ############################### 53 | # Naming Conventions # 54 | ############################### 55 | # Style Definitions 56 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 57 | # Use PascalCase for constant fields 58 | dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion 59 | dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields 60 | dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style 61 | dotnet_naming_symbols.constant_fields.applicable_kinds = field 62 | dotnet_naming_symbols.constant_fields.applicable_accessibilities = * 63 | dotnet_naming_symbols.constant_fields.required_modifiers = const 64 | 65 | ############################### 66 | # C# Coding Conventions # 67 | ############################### 68 | [*.cs] 69 | # var preferences 70 | csharp_style_var_for_built_in_types = false:warning 71 | csharp_style_var_when_type_is_apparent = true:warning 72 | csharp_style_var_elsewhere = false:suggestion 73 | # Expression-bodied members 74 | csharp_style_expression_bodied_methods = false:silent 75 | csharp_style_expression_bodied_constructors = false:silent 76 | csharp_style_expression_bodied_operators = false:silent 77 | csharp_style_expression_bodied_properties = true:silent 78 | csharp_style_expression_bodied_indexers = true:silent 79 | csharp_style_expression_bodied_accessors = true:silent 80 | # Pattern matching preferences 81 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 82 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 83 | # Null-checking preferences 84 | csharp_style_throw_expression = true:suggestion 85 | csharp_style_conditional_delegate_call = true:warning 86 | # Modifier preferences 87 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion 88 | # Expression-level preferences 89 | csharp_prefer_braces = true:silent 90 | csharp_style_deconstructed_variable_declaration = true:suggestion 91 | csharp_prefer_simple_default_expression = true:suggestion 92 | csharp_style_pattern_local_over_anonymous_function = true:suggestion 93 | csharp_style_inlined_variable_declaration = true:suggestion 94 | 95 | ############################### 96 | # C# Formatting Rules # 97 | ############################### 98 | # New line preferences 99 | csharp_new_line_before_open_brace = all 100 | csharp_new_line_before_else = true 101 | csharp_new_line_before_catch = true 102 | csharp_new_line_before_finally = true 103 | csharp_new_line_before_members_in_object_initializers = true 104 | csharp_new_line_before_members_in_anonymous_types = true 105 | csharp_new_line_between_query_expression_clauses = true 106 | # Indentation preferences 107 | csharp_indent_case_contents = true 108 | csharp_indent_switch_labels = true 109 | csharp_indent_labels = flush_left 110 | # Space preferences 111 | csharp_space_after_cast = false 112 | csharp_space_after_keywords_in_control_flow_statements = true 113 | csharp_space_between_method_call_parameter_list_parentheses = false 114 | csharp_space_between_method_declaration_parameter_list_parentheses = false 115 | csharp_space_between_parentheses = false 116 | csharp_space_before_colon_in_inheritance_clause = true 117 | csharp_space_after_colon_in_inheritance_clause = true 118 | csharp_space_around_binary_operators = before_and_after 119 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 120 | csharp_space_between_method_call_name_and_opening_parenthesis = false 121 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 122 | # Wrapping preferences 123 | csharp_preserve_single_line_statements = true 124 | csharp_preserve_single_line_blocks = true -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.cs text diff=csharp 7 | *.xaml text 8 | *.txt text 9 | *.tt text 10 | *.ps1 text 11 | *.cmd text 12 | *.msbuild text 13 | *.md text 14 | 15 | *.sln text eol=crlf merge=union 16 | *.csproj text merge=union 17 | *.vbproj text merge=union 18 | *.fsproj text merge=union 19 | *.dbproj text merge=union 20 | 21 | 22 | # Binary files 23 | *.png binary 24 | *.jpg binary 25 | *.dll binary 26 | *.exe binary -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [KeRNeLith] -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] " 5 | labels: bug 6 | assignees: KeRNeLith 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] " 5 | labels: enhancement 6 | assignees: KeRNeLith 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at kernelith@live.fr. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CleanSolution.ps1: -------------------------------------------------------------------------------- 1 | Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse } -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | 8 | true 9 | 10 | Alexandre Rabérin 11 | Alexandre Rabérin 12 | Alexandre Rabérin 13 | 14 | true 15 | MIT 16 | https://github.com/KeRNeLith/ImmediateReflection 17 | GitHub 18 | https://github.com/KeRNeLith/ImmediateReflection 19 | 20 | 21 | 22 | 23 | prompt 24 | 4 25 | 26 | 27 | true 28 | full 29 | false 30 | DEBUG;TRACE 31 | 32 | 33 | portable 34 | true 35 | JETBRAINS_ANNOTATIONS 36 | 37 | 38 | 39 | 40 | 7 41 | 42 | 43 | 44 | true 45 | ..\..\ImmediateReflection.snk 46 | $(DefineConstants);DEPLOY_BUILD; 47 | 48 | 49 | -------------------------------------------------------------------------------- /ImmediateReflection.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.2.32526.322 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ImmediateReflection.CommonInternals", "src\ImmediateReflection.CommonInternals\ImmediateReflection.CommonInternals.shproj", "{CE984360-54F0-406F-B8A9-E75897DAED3B}" 6 | EndProject 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImmediateReflection", "src\ImmediateReflection\ImmediateReflection.csproj", "{D5762C6B-C87B-28BB-C2A8-60B33343641D}" 8 | EndProject 9 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImmediateReflection.Tests", "tests\ImmediateReflection.Tests\ImmediateReflection.Tests.csproj", "{125C0F86-EA89-B12B-AEDF-B83E2B9623AC}" 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmark", "Benchmark", "{22937B93-4129-4F68-AB14-F7AFE020BA8F}" 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImmediateReflection.Benchmark", "benchmarks\ImmediateReflection.Benchmark\ImmediateReflection.Benchmark.csproj", "{952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0}" 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {D5762C6B-C87B-28BB-C2A8-60B33343641D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {D5762C6B-C87B-28BB-C2A8-60B33343641D}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {D5762C6B-C87B-28BB-C2A8-60B33343641D}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {D5762C6B-C87B-28BB-C2A8-60B33343641D}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {125C0F86-EA89-B12B-AEDF-B83E2B9623AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {125C0F86-EA89-B12B-AEDF-B83E2B9623AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {125C0F86-EA89-B12B-AEDF-B83E2B9623AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {125C0F86-EA89-B12B-AEDF-B83E2B9623AC}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0}.Release|Any CPU.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(NestedProjects) = preSolution 38 | {952EA9EF-9206-4BD8-8F9E-3CBAB655BCD0} = {22937B93-4129-4F68-AB14-F7AFE020BA8F} 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {D51F43F6-C27F-40EE-A4F2-CA21506D9B97} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /ImmediateReflection.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | DO_NOT_SHOW 6 | 7 | DO_NOT_SHOW 8 | 9 | DO_NOT_SHOW 10 | 11 | DO_NOT_SHOW 12 | 13 | DO_NOT_SHOW 14 | 15 | HINT 16 | 17 | DO_NOT_SHOW 18 | 19 | HINT 20 | 21 | DO_NOT_SHOW 22 | 23 | HINT 24 | 25 | DO_NOT_SHOW 26 | 27 | DO_NOT_SHOW 28 | 29 | DO_NOT_SHOW 30 | 31 | DO_NOT_SHOW 32 | 33 | SUGGESTION 34 | 35 | SUGGESTION 36 | 37 | SUGGESTION 38 | 39 | DO_NOT_SHOW 40 | 41 | DO_NOT_SHOW 42 | 43 | HINT 44 | 45 | SUGGESTION 46 | 47 | SUGGESTION 48 | 49 | DO_NOT_SHOW 50 | 51 | SUGGESTION 52 | 53 | 54 | FR 55 | US 56 | <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> 57 | -------------------------------------------------------------------------------- /ImmediateReflection.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeRNeLith/ImmediateReflection/206f8b97266dbb13bbb8fc630b6c404bd77fd593/ImmediateReflection.snk -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 KeRNeLith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | ## What's new in 2.0.0 September 5 2022 4 | ### Updates: 5 | * Update some serialization implementations for ImmediateReflection core types. 6 | * Dynamic methods generated by ImmediateReflection always use the ImmediateReflection module. 7 | 8 | ### Misc: 9 | * Get rid of targets anterior to .NET Framework 4.0. 10 | * Add target .NET Standard 2.1 to simplify dependency tree when used. 11 | * Assembly is CLS compliant (Common Language Specification). 12 | 13 | ## What's new in 1.6.1 September 4 2022 14 | ### Fixes: 15 | * Fix wrong generated IL code for copy constructor under .NET5+ target. 16 | 17 | ## What's new in 1.6.0 August 31 2020 18 | ### Fixes: 19 | * ImmediateType properly handle type having redefined properties with a type different from initial type. 20 | 21 | ### New: 22 | * Use signing key to strong name library assemby. 23 | 24 | ### Misc: 25 | * JetBrains.Annotations are embedded in the assembly (internal). 26 | 27 | ## What's new in 1.5.0 January 23 2020 28 | ### Fixes: 29 | * IsDefined/GetAttribute(s) properly handle get of attribute when dealing inheriting attributes. 30 | 31 | ### New: 32 | * All ImmediateReflection types are serializable via C# standard serialization. 33 | 34 | ### Misc: 35 | * JetBrains.Annotations are no more embedded in the assembly, replaced by a private reference to official NuGet. 36 | * Minor optimization. 37 | 38 | ## What's new in 1.4.1 September 2 2019 39 | ### Fixes: 40 | * Properly handle null parameter for Copy and TryCopy (return null). 41 | 42 | ### Updates: 43 | * Copy and TryCopy consider string and Type as copyable types and return themselves if asked. 44 | 45 | ## What's new in 1.4.0 September 1 2019 46 | ### New: 47 | * Add an access to the Declaring Type directly through ImmediateType, ImmediateProperty and ImmediateField. 48 | * Add an access to the Base Type directly through ImmediateType. 49 | * Add CopyConstructorDelegate delegate. 50 | * Add the possibility to call Copy constructor in a faster way than Activator from ImmediateType. 51 | * Add a type extension to check if a type has a default constructor. 52 | * Add type extensions to check if a type has a copy constructor and to directly call it. 53 | * Add object extensions to check if an instance can be copied by a copy constructor and to directly call it. 54 | 55 | ### Updates: 56 | * Globally optimize the library by reducing the number of redundant null checks. 57 | * Slightly optimize the branching in generated code. 58 | 59 | --- 60 | 61 | ## What's new in 1.3.0 July 23 2019 62 | ### New: 63 | * Add type extensions to directly call a default constructor delegate from a Type (without ImmediateType). 64 | * Add type extensions to directly call a constructor delegate from a Type (without ImmediateType). 65 | 66 | ### Fixes: 67 | * ImmediateType properly handle arrays which were crashing before. 68 | 69 | ### Updates: 70 | * Default constructor delegates available via ImmediateType are now cached and shared across several instance of ImmediateType. 71 | * ImmediateProperty are now cached and shared across several instance of ImmediateType. 72 | * ImmediateField are now cached and shared across several instance of ImmediateType. 73 | 74 | --- 75 | 76 | ## What's new in 1.2.0 July 18 2019 77 | ### New: 78 | * Add ConstructorDelegate delegate. 79 | 80 | ### Fixes: 81 | * Classes with indexed properties does not crash anymore. 82 | 83 | ### Updates: 84 | * Lazily initialize fields property of ImmediateType. 85 | 86 | --- 87 | 88 | ## What's new in 1.1.0 June 24 2019 89 | ### Updates: 90 | * Improve performances of memory caching within the library. 91 | * Extend support of built-in cache to every target. 92 | * Make some methods only available as extensions accessible as normal methods on targets not supporting extensions. 93 | * IL generated methods are now prefixed to help identify them. 94 | 95 | ### Misc: 96 | * API Reference and documentation generated based on sources. 97 | 98 | --- 99 | 100 | ## What's new in 1.0.0 May 31 2019 101 | ### Fixes: 102 | * Properly supports static readonly and constant fields. 103 | * Properly handle reflection on enumeration types. 104 | 105 | ### Updates: 106 | * Default flags taken into account when getting an ImmediateType are Public | Instance | Static 107 | * Get rid of cache system references replaced by a simpler internal caching system. 108 | * Extend caching support to target .NET Framework 4.0. 109 | 110 | ### New: 111 | * Add the possibility to call the default constructor of type in a faster way (with or without throw). 112 | * ImmediateType provides access to every members via Members/GetMembers()/indexed member APIs. 113 | * ImmediateType, ImmediateField and ImmediateProperty provide a faster access to attributes. 114 | * Extensions to retrieve Immediate Reflection types from standard types. 115 | * Extensions to retrieve attributes from standard MemberInfo. 116 | * Provide helpers to easily create strongly typed delegate to get/set properties. 117 | * Add an object wrapper that allows to get/set value on a specific object instance. 118 | 119 | ### Misc: 120 | * Improve library documentation. 121 | * Library is fully ReSharper annotated. 122 | 123 | --- 124 | 125 | ## What's new in 0.1.0 May 14 2019 126 | * First implementation of a fast ("immediate") access and usage of C# Reflection features. 127 | * Supports Type fields and properties getter/setter. -------------------------------------------------------------------------------- /SonarQube.Analysis.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | **/Externs/**/* 4 | -------------------------------------------------------------------------------- /benchmarks/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | false 8 | 9 | true 10 | 11 | 12 | 13 | 14 | latest 15 | 16 | -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Attributes/TestAttributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ImmediateReflection.Benchmark 4 | { 5 | [AttributeUsage(AttributeTargets.All)] 6 | public class TestClassAttribute : Attribute 7 | { 8 | } 9 | 10 | [AttributeUsage(AttributeTargets.All)] 11 | public class SecondTestClassAttribute : Attribute 12 | { 13 | } 14 | 15 | [AttributeUsage(AttributeTargets.All)] 16 | public class ThirdTestClassAttribute : Attribute 17 | { 18 | } 19 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Configs; 2 | using BenchmarkDotNet.Running; 3 | 4 | namespace ImmediateReflection.Benchmark 5 | { 6 | internal class Benchmark 7 | { 8 | /// 9 | /// Benchmark Main. 10 | /// 11 | public static void Main(string[] args) 12 | { 13 | #if DEBUG 14 | // Allow to run even if in Debug target (But Benchmark must be run in RELEASE in the end 15 | IConfig config = DefaultConfig.Instance.WithOptions(ConfigOptions.DisableOptimizationsValidator); 16 | #else 17 | IConfig config = DefaultConfig.Instance; 18 | #endif 19 | 20 | // Constructor 21 | BenchmarkRunner.Run(config); 22 | BenchmarkRunner.Run(config); 23 | BenchmarkRunner.Run(config); 24 | BenchmarkRunner.Run(config); 25 | 26 | // Single get/set 27 | BenchmarkRunner.Run(config); 28 | BenchmarkRunner.Run(config); 29 | BenchmarkRunner.Run(config); 30 | BenchmarkRunner.Run(config); 31 | 32 | // Multi get/set 33 | BenchmarkRunner.Run(config); 34 | BenchmarkRunner.Run(config); 35 | BenchmarkRunner.Run(config); 36 | BenchmarkRunner.Run(config); 37 | 38 | BenchmarkRunner.Run(config); 39 | BenchmarkRunner.Run(config); 40 | 41 | // Attributes 42 | BenchmarkRunner.Run(config); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/CopyConstructorBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BenchmarkDotNet.Attributes; 3 | using JetBrains.Annotations; 4 | 5 | namespace ImmediateReflection.Benchmark 6 | { 7 | /// 8 | /// Copy constructor benchmark class. 9 | /// 10 | public class CopyConstructorBenchmark : BenchmarkBase 11 | { 12 | [NotNull] 13 | private static readonly CopyableBenchmarkObject ObjectToCopy = new CopyableBenchmarkObject("Benchmark value"); 14 | 15 | [NotNull] 16 | private static readonly Func ExpressionConstructor = 17 | ExpressionHelpers.CreateCopyConstructor(); 18 | 19 | // Benchmark methods 20 | [Benchmark(Baseline = true)] 21 | public CopyableBenchmarkObject Direct_CopyConstructor() 22 | { 23 | return new CopyableBenchmarkObject(ObjectToCopy); 24 | } 25 | 26 | [Benchmark] 27 | public CopyableBenchmarkObject Activator_CopyConstructor() 28 | { 29 | return (CopyableBenchmarkObject)Activator.CreateInstance(CopyableBenchmarkObjectType, ObjectToCopy); 30 | } 31 | 32 | [Benchmark] 33 | public CopyableBenchmarkObject Expression_CopyConstructor() 34 | { 35 | return ExpressionConstructor(ObjectToCopy); 36 | } 37 | 38 | [Benchmark] 39 | public CopyableBenchmarkObject ImmediateType_CopyConstructor() 40 | { 41 | return (CopyableBenchmarkObject)ImmediateTypeCopyable.Copy(ObjectToCopy); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/DefaultConstructorBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BenchmarkDotNet.Attributes; 3 | using JetBrains.Annotations; 4 | 5 | namespace ImmediateReflection.Benchmark 6 | { 7 | /// 8 | /// Default constructor benchmark class. 9 | /// 10 | public class DefaultConstructorBenchmark : BenchmarkBase 11 | { 12 | [NotNull] 13 | private static readonly Func ExpressionConstructor = ExpressionHelpers.CreateDefaultConstructor(); 14 | 15 | // Benchmark methods 16 | [Benchmark(Baseline = true)] 17 | public BenchmarkObject Direct_Constructor() 18 | { 19 | return new BenchmarkObject(); 20 | } 21 | 22 | [Benchmark] 23 | public BenchmarkObject Activator_Constructor() 24 | { 25 | return (BenchmarkObject)Activator.CreateInstance(BenchmarkObjectType); 26 | } 27 | 28 | [Benchmark] 29 | public BenchmarkObject Expression_Constructor() 30 | { 31 | return ExpressionConstructor(); 32 | } 33 | 34 | [Benchmark] 35 | public BenchmarkObject FastMember_Constructor() 36 | { 37 | return (BenchmarkObject)TypeAccessor.CreateNew(); 38 | } 39 | 40 | [Benchmark] 41 | public BenchmarkObject ImmediateType_Constructor() 42 | { 43 | return (BenchmarkObject)ImmediateType.New(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/FieldGetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace ImmediateReflection.Benchmark 6 | { 7 | /// 8 | /// Field getter benchmark class. 9 | /// 10 | public class FieldGetterBenchmark : BenchmarkBase 11 | { 12 | // Benchmark methods 13 | [Benchmark(Baseline = true)] 14 | public int GetDirect_Field() 15 | { 16 | return BenchmarkObject._benchmarkField; 17 | } 18 | 19 | [Benchmark] 20 | public int GetFieldInfo_Field() 21 | { 22 | Type benchmarkType = BenchmarkObject.GetType(); 23 | FieldInfo benchmarkField = benchmarkType.GetField(BenchmarkObjectFieldName); 24 | // ReSharper disable once PossibleNullReferenceException 25 | return (int)benchmarkField.GetValue(BenchmarkObject); 26 | } 27 | 28 | [Benchmark] 29 | public int GetFieldInfoCache_Field() 30 | { 31 | return (int)FieldInfo.GetValue(BenchmarkObject); 32 | } 33 | 34 | [Benchmark] 35 | public int GetFastMember_Field() 36 | { 37 | return (int)TypeAccessor[BenchmarkObject, BenchmarkObjectFieldName]; 38 | } 39 | 40 | [Benchmark] 41 | public int GetImmediateField_Field() 42 | { 43 | return (int)ImmediateField.GetValue(BenchmarkObject); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/FieldMultiGetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace ImmediateReflection.Benchmark 6 | { 7 | /// 8 | /// Field multi getter benchmark class. 9 | /// 10 | public class FieldMultiGetterBenchmark : BenchmarkBase 11 | { 12 | // Benchmark methods 13 | [Benchmark(Baseline = true)] 14 | public string GetDirect_Field() 15 | { 16 | return $"{BenchmarkObject._benchmarkField}{BenchmarkObject2._benchmarkField}{BenchmarkObject3._benchmarkField}{BenchmarkObject4._benchmarkField}"; 17 | } 18 | 19 | [Benchmark] 20 | public string GetFieldInfo_Field() 21 | { 22 | Type benchmarkType = BenchmarkObject.GetType(); 23 | FieldInfo benchmarkField = benchmarkType.GetField(BenchmarkObjectFieldName); 24 | 25 | Type benchmarkType2 = BenchmarkObject2.GetType(); 26 | FieldInfo benchmarkField2 = benchmarkType2.GetField(BenchmarkObjectFieldName2); 27 | 28 | Type benchmarkType3 = BenchmarkObject3.GetType(); 29 | FieldInfo benchmarkField3 = benchmarkType3.GetField(BenchmarkObjectFieldName3); 30 | 31 | Type benchmarkType4 = BenchmarkObject4.GetType(); 32 | FieldInfo benchmarkField4 = benchmarkType4.GetField(BenchmarkObjectFieldName4); 33 | 34 | // ReSharper disable PossibleNullReferenceException 35 | return $"{(int)benchmarkField.GetValue(BenchmarkObject)}{(float)benchmarkField2.GetValue(BenchmarkObject2)}{(string)benchmarkField3.GetValue(BenchmarkObject3)}{(uint)benchmarkField4.GetValue(BenchmarkObject4)}"; 36 | // ReSharper restore PossibleNullReferenceException 37 | } 38 | 39 | [Benchmark] 40 | public string GetFieldInfoCache_Field() 41 | { 42 | return $"{(int)FieldInfo.GetValue(BenchmarkObject)}{(float)FieldInfo2.GetValue(BenchmarkObject2)}{(string)FieldInfo3.GetValue(BenchmarkObject3)}{(uint)FieldInfo4.GetValue(BenchmarkObject4)}"; 43 | } 44 | 45 | [Benchmark] 46 | public string GetFastMember_Field() 47 | { 48 | return $"{(int)TypeAccessor[BenchmarkObject, BenchmarkObjectFieldName]}{(float)TypeAccessor2[BenchmarkObject2, BenchmarkObjectFieldName2]}{(string)TypeAccessor3[BenchmarkObject3, BenchmarkObjectFieldName3]}{(uint)TypeAccessor4[BenchmarkObject4, BenchmarkObjectFieldName4]}"; 49 | } 50 | 51 | [Benchmark] 52 | public string GetImmediateField_Field() 53 | { 54 | return $"{(int)ImmediateField.GetValue(BenchmarkObject)}{(float)ImmediateField2.GetValue(BenchmarkObject2)}{(string)ImmediateField3.GetValue(BenchmarkObject3)}{(uint)ImmediateField4.GetValue(BenchmarkObject4)}"; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/FieldMultiSetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | using JetBrains.Annotations; 5 | 6 | namespace ImmediateReflection.Benchmark 7 | { 8 | /// 9 | /// Field multi setter benchmark class. 10 | /// 11 | public class FieldMultiSetterBenchmark : BenchmarkBase 12 | { 13 | private const int ValueToSet = 12; 14 | 15 | private const float ValueToSet2 = 14.1f; 16 | 17 | [NotNull] 18 | private const string ValueToSet3 = "Updated Benchmark Field"; 19 | 20 | private const uint ValueToSet4 = 6; 21 | 22 | // Benchmark methods 23 | [Benchmark(Baseline = true)] 24 | public void SetDirect_Field() 25 | { 26 | BenchmarkObject._benchmarkField = ValueToSet; 27 | BenchmarkObject2._benchmarkField = ValueToSet2; 28 | BenchmarkObject3._benchmarkField = ValueToSet3; 29 | BenchmarkObject4._benchmarkField = ValueToSet4; 30 | } 31 | 32 | [Benchmark] 33 | public void SetFieldInfo_Field() 34 | { 35 | Type benchmarkType = BenchmarkObject.GetType(); 36 | FieldInfo benchmarkField = benchmarkType.GetField(BenchmarkObjectFieldName); 37 | 38 | Type benchmarkType2 = BenchmarkObject2.GetType(); 39 | FieldInfo benchmarkField2 = benchmarkType2.GetField(BenchmarkObjectFieldName2); 40 | 41 | Type benchmarkType3 = BenchmarkObject3.GetType(); 42 | FieldInfo benchmarkField3 = benchmarkType3.GetField(BenchmarkObjectFieldName3); 43 | 44 | Type benchmarkType4 = BenchmarkObject4.GetType(); 45 | FieldInfo benchmarkField4 = benchmarkType4.GetField(BenchmarkObjectFieldName4); 46 | 47 | // ReSharper disable PossibleNullReferenceException 48 | benchmarkField.SetValue(BenchmarkObject, ValueToSet); 49 | benchmarkField2.SetValue(BenchmarkObject2, ValueToSet2); 50 | benchmarkField3.SetValue(BenchmarkObject3, ValueToSet3); 51 | benchmarkField4.SetValue(BenchmarkObject4, ValueToSet4); 52 | // ReSharper restore PossibleNullReferenceException 53 | } 54 | 55 | [Benchmark] 56 | public void SetFieldInfoCache_Field() 57 | { 58 | FieldInfo.SetValue(BenchmarkObject, ValueToSet); 59 | FieldInfo2.SetValue(BenchmarkObject2, ValueToSet2); 60 | FieldInfo3.SetValue(BenchmarkObject3, ValueToSet3); 61 | FieldInfo4.SetValue(BenchmarkObject4, ValueToSet4); 62 | } 63 | 64 | [Benchmark] 65 | public void SetFastMember_Field() 66 | { 67 | TypeAccessor[BenchmarkObject, BenchmarkObjectFieldName] = ValueToSet; 68 | TypeAccessor2[BenchmarkObject2, BenchmarkObjectFieldName2] = ValueToSet2; 69 | TypeAccessor3[BenchmarkObject3, BenchmarkObjectFieldName3] = ValueToSet3; 70 | TypeAccessor4[BenchmarkObject4, BenchmarkObjectFieldName4] = ValueToSet4; 71 | } 72 | 73 | [Benchmark] 74 | public void SetImmediateField_Field() 75 | { 76 | ImmediateField.SetValue(BenchmarkObject, ValueToSet); 77 | ImmediateField2.SetValue(BenchmarkObject2, ValueToSet2); 78 | ImmediateField3.SetValue(BenchmarkObject3, ValueToSet3); 79 | ImmediateField4.SetValue(BenchmarkObject4, ValueToSet4); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/FieldSetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace ImmediateReflection.Benchmark 6 | { 7 | /// 8 | /// Field setter benchmark class. 9 | /// 10 | public class FieldSetterBenchmark : BenchmarkBase 11 | { 12 | private const int ValueToSet = 12; 13 | 14 | // Benchmark methods 15 | [Benchmark(Baseline = true)] 16 | public void SetDirect_Field() 17 | { 18 | BenchmarkObject._benchmarkField = ValueToSet; 19 | } 20 | 21 | [Benchmark] 22 | public void SetFieldInfo_Field() 23 | { 24 | Type benchmarkType = BenchmarkObject.GetType(); 25 | FieldInfo benchmarkField = benchmarkType.GetField(BenchmarkObjectFieldName); 26 | // ReSharper disable once PossibleNullReferenceException 27 | benchmarkField.SetValue(BenchmarkObject, ValueToSet); 28 | } 29 | 30 | [Benchmark] 31 | public void SetFieldInfoCache_Field() 32 | { 33 | FieldInfo.SetValue(BenchmarkObject, ValueToSet); 34 | } 35 | 36 | [Benchmark] 37 | public void SetFastMember_Field() 38 | { 39 | TypeAccessor[BenchmarkObject, BenchmarkObjectFieldName] = ValueToSet; 40 | } 41 | 42 | [Benchmark] 43 | public void SetImmediateField_Field() 44 | { 45 | ImmediateField.SetValue(BenchmarkObject, ValueToSet); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/GetAttributesBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using BenchmarkDotNet.Attributes; 5 | using FastMember; 6 | using JetBrains.Annotations; 7 | 8 | namespace ImmediateReflection.Benchmark 9 | { 10 | public class GetAttributesBenchmark : BenchmarkBase 11 | { 12 | [NotNull] 13 | private static readonly Type AttributesBenchmarkObjectType = typeof(AttributesBenchmarkObject); 14 | 15 | [NotNull] private static readonly PropertyInfo AttributesBenchmarkProperty = 16 | AttributesBenchmarkObjectType.GetProperty(nameof(AttributesBenchmarkObject.TestProperty)) 17 | ?? throw new InvalidOperationException("Property does not exist."); 18 | 19 | [NotNull, ItemNotNull] 20 | private static readonly Attribute[] CachedAttributes = AttributesBenchmarkProperty.GetCustomAttributes(false).OfType().ToArray(); 21 | 22 | [CanBeNull] 23 | // ReSharper disable once UnusedMethodReturnValue.Local 24 | private static TAttribute GetAttributeFromCache() 25 | where TAttribute : Attribute 26 | { 27 | return (TAttribute)CachedAttributes.FirstOrDefault(attribute => attribute is TAttribute); 28 | } 29 | 30 | [NotNull] 31 | private static readonly Member FastMemberProperty = FastMember.TypeAccessor.Create(AttributesBenchmarkObjectType).GetMembers()[0]; 32 | 33 | [NotNull] 34 | private static readonly ImmediateProperty AttributesImmediateProperty = new ImmediateProperty(AttributesBenchmarkProperty); 35 | 36 | // Benchmark methods 37 | [Benchmark(Baseline = true)] 38 | public void Property_GetAttribute() 39 | { 40 | AttributesBenchmarkProperty.GetCustomAttribute(false); 41 | AttributesBenchmarkProperty.GetCustomAttribute(false); 42 | } 43 | 44 | [Benchmark] 45 | public void PropertyCache_GetAttribute() 46 | { 47 | GetAttributeFromCache(); 48 | GetAttributeFromCache(); 49 | } 50 | 51 | [Benchmark] 52 | public void FastMember_GetAttribute() 53 | { 54 | FastMemberProperty.GetAttribute(typeof(TestClassAttribute), false); 55 | FastMemberProperty.GetAttribute(typeof(ThirdTestClassAttribute), false); 56 | } 57 | 58 | [Benchmark] 59 | public void ImmediateProperty_GetAttribute() 60 | { 61 | // ReSharper disable ReturnValueOfPureMethodIsNotUsed 62 | AttributesImmediateProperty.GetAttribute(); 63 | AttributesImmediateProperty.GetAttribute(); 64 | // ReSharper restore ReturnValueOfPureMethodIsNotUsed 65 | } 66 | 67 | [Benchmark] 68 | public void Property_ByImmediateReflection_GetAttribute() 69 | { 70 | AttributesBenchmarkProperty.GetImmediateAttribute(); 71 | AttributesBenchmarkProperty.GetImmediateAttribute(); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/MultiCopyConstructorBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BenchmarkDotNet.Attributes; 3 | using JetBrains.Annotations; 4 | 5 | // ReSharper disable UnusedVariable 6 | 7 | namespace ImmediateReflection.Benchmark 8 | { 9 | /// 10 | /// Copy constructor benchmark class. 11 | /// 12 | public class MultiCopyConstructorBenchmark : BenchmarkBase 13 | { 14 | [NotNull] 15 | private static readonly CopyableBenchmarkObject ObjectToCopy = new CopyableBenchmarkObject("Benchmark value"); 16 | 17 | [NotNull] 18 | private static readonly CopyableBenchmarkObject2 ObjectToCopy2 = new CopyableBenchmarkObject2(42); 19 | 20 | [NotNull] 21 | private static readonly CopyableBenchmarkObject3 ObjectToCopy3 = new CopyableBenchmarkObject3(12.5); 22 | 23 | [NotNull] 24 | private static readonly CopyableBenchmarkObject4 ObjectToCopy4 = new CopyableBenchmarkObject4(5); 25 | 26 | [NotNull] 27 | private static readonly Func ExpressionConstructor = 28 | ExpressionHelpers.CreateCopyConstructor(); 29 | 30 | [NotNull] 31 | private static readonly Func ExpressionConstructor2 = 32 | ExpressionHelpers.CreateCopyConstructor(); 33 | 34 | [NotNull] 35 | private static readonly Func ExpressionConstructor3 = 36 | ExpressionHelpers.CreateCopyConstructor(); 37 | 38 | [NotNull] 39 | private static readonly Func ExpressionConstructor4 = 40 | ExpressionHelpers.CreateCopyConstructor(); 41 | 42 | // Benchmark methods 43 | [Benchmark(Baseline = true)] 44 | public void Direct_CopyConstructor() 45 | { 46 | // ReSharper disable ObjectCreationAsStatement 47 | var obj1 = new CopyableBenchmarkObject(ObjectToCopy); 48 | var obj2 = new CopyableBenchmarkObject2(ObjectToCopy2); 49 | var obj3 = new CopyableBenchmarkObject3(ObjectToCopy3); 50 | var obj4 = new CopyableBenchmarkObject4(ObjectToCopy4); 51 | // ReSharper restore ObjectCreationAsStatement 52 | } 53 | 54 | [Benchmark] 55 | public void Activator_CopyConstructor() 56 | { 57 | var obj1 = (CopyableBenchmarkObject)Activator.CreateInstance(CopyableBenchmarkObjectType, ObjectToCopy); 58 | var obj2 = (CopyableBenchmarkObject2)Activator.CreateInstance(CopyableBenchmarkObjectType2, ObjectToCopy2); 59 | var obj3 = (CopyableBenchmarkObject3)Activator.CreateInstance(CopyableBenchmarkObjectType3, ObjectToCopy3); 60 | var obj4 = (CopyableBenchmarkObject4)Activator.CreateInstance(CopyableBenchmarkObjectType4, ObjectToCopy4); 61 | } 62 | 63 | [Benchmark] 64 | public void Expression_CopyConstructor() 65 | { 66 | CopyableBenchmarkObject obj1 = ExpressionConstructor(ObjectToCopy); 67 | CopyableBenchmarkObject2 obj2 = ExpressionConstructor2(ObjectToCopy2); 68 | CopyableBenchmarkObject3 obj3 = ExpressionConstructor3(ObjectToCopy3); 69 | CopyableBenchmarkObject4 obj4 = ExpressionConstructor4(ObjectToCopy4); 70 | } 71 | 72 | [Benchmark] 73 | public void ImmediateType_CopyConstructor() 74 | { 75 | var obj1 = (CopyableBenchmarkObject)ImmediateTypeCopyable.Copy(ObjectToCopy); 76 | var obj2 = (CopyableBenchmarkObject2)ImmediateTypeCopyable2.Copy(ObjectToCopy2); 77 | var obj3 = (CopyableBenchmarkObject3)ImmediateTypeCopyable3.Copy(ObjectToCopy3); 78 | var obj4 = (CopyableBenchmarkObject4)ImmediateTypeCopyable4.Copy(ObjectToCopy4); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/MultiDefaultConstructorBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BenchmarkDotNet.Attributes; 3 | using JetBrains.Annotations; 4 | 5 | // ReSharper disable UnusedVariable 6 | 7 | namespace ImmediateReflection.Benchmark 8 | { 9 | /// 10 | /// Default constructor benchmark class. 11 | /// 12 | public class MultiDefaultConstructorBenchmark : BenchmarkBase 13 | { 14 | [NotNull] 15 | private static readonly Func ExpressionConstructor = ExpressionHelpers.CreateDefaultConstructor(); 16 | 17 | [NotNull] 18 | private static readonly Func ExpressionConstructor2 = ExpressionHelpers.CreateDefaultConstructor(); 19 | 20 | [NotNull] 21 | private static readonly Func ExpressionConstructor3 = ExpressionHelpers.CreateDefaultConstructor(); 22 | 23 | [NotNull] 24 | private static readonly Func ExpressionConstructor4 = ExpressionHelpers.CreateDefaultConstructor(); 25 | 26 | // Benchmark methods 27 | [Benchmark(Baseline = true)] 28 | public void Direct_Constructor() 29 | { 30 | // ReSharper disable ObjectCreationAsStatement 31 | var obj1 = new BenchmarkObject(); 32 | var obj2 = new BenchmarkObject2(); 33 | var obj3 = new BenchmarkObject3(); 34 | var obj4 = new BenchmarkObject4(); 35 | // ReSharper restore ObjectCreationAsStatement 36 | } 37 | 38 | [Benchmark] 39 | public void Activator_Constructor() 40 | { 41 | var obj1 = (BenchmarkObject)Activator.CreateInstance(BenchmarkObjectType); 42 | var obj2 = (BenchmarkObject2)Activator.CreateInstance(BenchmarkObjectType2); 43 | var obj3 = (BenchmarkObject3)Activator.CreateInstance(BenchmarkObjectType3); 44 | var obj4 = (BenchmarkObject4)Activator.CreateInstance(BenchmarkObjectType4); 45 | } 46 | 47 | [Benchmark] 48 | public void Expression_Constructor() 49 | { 50 | BenchmarkObject obj1 = ExpressionConstructor(); 51 | BenchmarkObject2 obj2 = ExpressionConstructor2(); 52 | BenchmarkObject3 obj3 = ExpressionConstructor3(); 53 | BenchmarkObject4 obj4 = ExpressionConstructor4(); 54 | } 55 | 56 | [Benchmark] 57 | public void FastMember_Constructor() 58 | { 59 | var obj1 = (BenchmarkObject)TypeAccessor.CreateNew(); 60 | var obj2 = (BenchmarkObject2)TypeAccessor2.CreateNew(); 61 | var obj3 = (BenchmarkObject3)TypeAccessor3.CreateNew(); 62 | var obj4 = (BenchmarkObject4)TypeAccessor4.CreateNew(); 63 | } 64 | 65 | [Benchmark] 66 | public void ImmediateType_Constructor() 67 | { 68 | var obj1 = (BenchmarkObject)ImmediateType.New(); 69 | var obj2 = (BenchmarkObject2)ImmediateType2.New(); 70 | var obj3 = (BenchmarkObject3)ImmediateType3.New(); 71 | var obj4 = (BenchmarkObject4)ImmediateType4.New(); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/PropertyGetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | using JetBrains.Annotations; 5 | using Sigil; 6 | 7 | namespace ImmediateReflection.Benchmark 8 | { 9 | /// 10 | /// Property getter benchmark class. 11 | /// 12 | public class PropertyGetterBenchmark : BenchmarkBase 13 | { 14 | [NotNull] 15 | private static readonly Func GetterDelegate = (Func) 16 | Delegate.CreateDelegate(typeof(Func), null, PropertyInfo.GetGetMethod()); 17 | 18 | [NotNull] 19 | private static readonly Delegate DynamicGetterDelegate = Delegate.CreateDelegate( 20 | typeof(Func), null, PropertyInfo.GetGetMethod()); 21 | 22 | [NotNull] 23 | private static readonly Func SigilEmitGetter = Emit> 24 | .NewDynamicMethod("GetProperty") 25 | .LoadArgument(0) 26 | .Call(PropertyInfo.GetGetMethod()) 27 | .Return() 28 | .CreateDelegate(); 29 | 30 | [NotNull] 31 | private static readonly Func ExpressionGetter = ExpressionHelpers.CreateGetter(PropertyInfo); 32 | 33 | // Benchmark methods 34 | [Benchmark(Baseline = true)] 35 | public string GetDirect_Property() 36 | { 37 | return BenchmarkObject.BenchmarkProperty; 38 | } 39 | 40 | [Benchmark] 41 | public string GetDelegate_Property() 42 | { 43 | return GetterDelegate(BenchmarkObject); 44 | } 45 | 46 | [Benchmark] 47 | public string GetDynamicDelegate_Property() 48 | { 49 | return (string)DynamicGetterDelegate.DynamicInvoke(BenchmarkObject); 50 | } 51 | 52 | [Benchmark] 53 | public string GetPropertyInfo_Property() 54 | { 55 | Type benchmarkType = BenchmarkObject.GetType(); 56 | PropertyInfo benchmarkProperty = benchmarkType.GetProperty(BenchmarkObjectPropertyName); 57 | // ReSharper disable once PossibleNullReferenceException 58 | return (string)benchmarkProperty.GetValue(BenchmarkObject); 59 | } 60 | 61 | [Benchmark] 62 | public string GetPropertyInfoCache_Property() 63 | { 64 | return (string)PropertyInfo.GetValue(BenchmarkObject); 65 | } 66 | 67 | [Benchmark] 68 | public string GetSigilEmit_Property() 69 | { 70 | return SigilEmitGetter(BenchmarkObject); 71 | } 72 | 73 | [Benchmark] 74 | public string GetExpression_Property() 75 | { 76 | return (string)ExpressionGetter(BenchmarkObject); 77 | } 78 | 79 | [Benchmark] 80 | public string GetFastMember_Property() 81 | { 82 | return (string)TypeAccessor[BenchmarkObject, BenchmarkObjectPropertyName]; 83 | } 84 | 85 | [Benchmark] 86 | public string GetImmediateProperty_Property() 87 | { 88 | return (string)ImmediateProperty.GetValue(BenchmarkObject); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/PropertyGetterOverObjectsBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Linq; 3 | using System.Reflection; 4 | using BenchmarkDotNet.Attributes; 5 | using Fasterflect; 6 | using FlashReflection; 7 | using JetBrains.Annotations; 8 | 9 | namespace ImmediateReflection.Benchmark 10 | { 11 | /// 12 | /// Property getter over multiple objects benchmark class. 13 | /// 14 | public class PropertyGetterOverObjectsBenchmark : ObjectsBenchmarkBase 15 | { 16 | // Benchmark methods 17 | [Benchmark(Baseline = true)] 18 | public void Reflection_PropertyGet_BenchmarkObject() 19 | { 20 | foreach (object obj in BenchmarkObjects) 21 | { 22 | GetPropertyReflection(obj); 23 | } 24 | } 25 | 26 | [Benchmark] 27 | public void ReflectionCache_PropertyGet_BenchmarkObject() 28 | { 29 | foreach (object obj in BenchmarkObjects) 30 | { 31 | GetPropertyReflectionCache(obj); 32 | } 33 | } 34 | 35 | [Benchmark] 36 | public void HyperDescriptor_PropertyGet_BenchmarkObject() 37 | { 38 | foreach (object obj in BenchmarkObjects) 39 | { 40 | GetPropertyHyperDescriptor(obj); 41 | } 42 | } 43 | 44 | [Benchmark] 45 | public void FastMember_PropertyGet_BenchmarkObject() 46 | { 47 | foreach (object obj in BenchmarkObjects) 48 | { 49 | GetPropertyFastMember(obj); 50 | } 51 | } 52 | 53 | [Benchmark] 54 | public void FlashReflection_PropertyGet_BenchmarkObject() 55 | { 56 | foreach (object obj in BenchmarkObjects) 57 | { 58 | GetPropertyFlashReflection(obj); 59 | } 60 | } 61 | 62 | [Benchmark] 63 | public void ImmediateReflection_PropertyGet_BenchmarkObject() 64 | { 65 | foreach (object obj in BenchmarkObjects) 66 | { 67 | GetPropertyImmediateReflection(obj); 68 | } 69 | } 70 | 71 | [Benchmark] 72 | public void WithFasterflect_PropertyGet_BenchmarkObject() 73 | { 74 | foreach (object obj in BenchmarkObjects) 75 | { 76 | GetPropertyFasterflect(obj); 77 | } 78 | } 79 | 80 | [Benchmark] 81 | public void Reflection_PropertyGet_Mixed_BenchmarkObject() 82 | { 83 | foreach (object obj in BenchmarkMixedObjects) 84 | { 85 | GetPropertyReflection(obj); 86 | } 87 | } 88 | 89 | [Benchmark] 90 | public void ReflectionCache_PropertyGet_Mixed_BenchmarkObject() 91 | { 92 | foreach (object obj in BenchmarkMixedObjects) 93 | { 94 | GetPropertyReflectionCache(obj); 95 | } 96 | } 97 | 98 | [Benchmark] 99 | public void HyperDescriptor_PropertyGet_Mixed_BenchmarkObject() 100 | { 101 | foreach (object obj in BenchmarkMixedObjects) 102 | { 103 | GetPropertyHyperDescriptor(obj); 104 | } 105 | } 106 | 107 | [Benchmark] 108 | public void FastMember_PropertyGet_Mixed_BenchmarkObject() 109 | { 110 | foreach (object obj in BenchmarkMixedObjects) 111 | { 112 | GetPropertyFastMember(obj); 113 | } 114 | } 115 | 116 | [Benchmark] 117 | public void FlashReflection_PropertyGet_Mixed_BenchmarkObject() 118 | { 119 | foreach (object obj in BenchmarkMixedObjects) 120 | { 121 | GetPropertyFlashReflection(obj); 122 | } 123 | } 124 | 125 | [Benchmark] 126 | public void ImmediateReflection_PropertyGet_Mixed_BenchmarkObject() 127 | { 128 | foreach (object obj in BenchmarkMixedObjects) 129 | { 130 | GetPropertyImmediateReflection(obj); 131 | } 132 | } 133 | 134 | [Benchmark] 135 | public void Fasterflect_PropertyGet_Mixed_BenchmarkObject() 136 | { 137 | foreach (object obj in BenchmarkMixedObjects) 138 | { 139 | GetPropertyFasterflect(obj); 140 | } 141 | } 142 | 143 | #region Helper methods 144 | 145 | public object GetPropertyReflection([NotNull] object obj) 146 | { 147 | PropertyInfo propertyInfo = obj.GetType().GetProperty(UIntArrayPropertyName); 148 | if (propertyInfo is null || propertyInfo.PropertyType != typeof(uint[])) 149 | return null; 150 | 151 | return propertyInfo.GetValue(obj); 152 | } 153 | 154 | public object GetPropertyReflectionCache([NotNull] object obj) 155 | { 156 | if (obj.GetType() != typeof(ObjectsBenchmarkObject1)) 157 | return null; 158 | 159 | return UIntArrayPropertyInfo.GetValue(obj); 160 | } 161 | 162 | public object GetPropertyHyperDescriptor([NotNull] object obj) 163 | { 164 | PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(obj).Find(UIntArrayPropertyName, false); 165 | return propertyDescriptor?.GetValue(obj); 166 | } 167 | 168 | public object GetPropertyFastMember([NotNull] object obj) 169 | { 170 | FastMember.TypeAccessor accessor = FastMember.TypeAccessor.Create(obj.GetType()); 171 | bool hasProperty = accessor.GetMembers().Any(m => m.Name == UIntArrayPropertyName); 172 | if (!hasProperty) 173 | return null; 174 | 175 | return accessor[obj, UIntArrayPropertyName]; 176 | } 177 | 178 | public object GetPropertyFlashReflection([NotNull] object obj) 179 | { 180 | ReflectionType type = ReflectionCache.Instance.GetReflectionType(obj.GetType()); 181 | ReflectionProperty property = type.Properties[UIntArrayPropertyName]; 182 | 183 | return property?.GetValue(obj); 184 | } 185 | 186 | public object GetPropertyImmediateReflection([NotNull] object obj) 187 | { 188 | ImmediateType accessor = ImmediateReflection.TypeAccessor.Get(obj.GetType()); 189 | ImmediateProperty property = accessor.GetProperty(UIntArrayPropertyName); 190 | 191 | return property?.GetValue(obj); 192 | } 193 | 194 | public object GetPropertyFasterflect([NotNull] object obj) 195 | { 196 | return obj.TryGetPropertyValue(UIntArrayPropertyName); 197 | } 198 | 199 | #endregion 200 | } 201 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/PropertySetterBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BenchmarkDotNet.Attributes; 4 | using JetBrains.Annotations; 5 | using Sigil; 6 | 7 | namespace ImmediateReflection.Benchmark 8 | { 9 | /// 10 | /// Property setter benchmark class. 11 | /// 12 | public class PropertySetterBenchmark : BenchmarkBase 13 | { 14 | [NotNull] 15 | private static readonly Action SetterDelegate = (Action) 16 | Delegate.CreateDelegate(typeof(Action), null, PropertyInfo.GetSetMethod()); 17 | 18 | [NotNull] 19 | private static readonly Delegate DynamicSetterDelegate = Delegate.CreateDelegate( 20 | typeof(Action), null, PropertyInfo.GetSetMethod()); 21 | 22 | [NotNull] 23 | private static readonly Action SigilEmitSetter = Emit> 24 | .NewDynamicMethod("SetProperty") 25 | .LoadArgument(0) 26 | .LoadArgument(1) 27 | .Call(PropertyInfo.GetSetMethod()) 28 | .Return() 29 | .CreateDelegate(); 30 | 31 | [NotNull] 32 | private static readonly Action ExpressionSetter = ExpressionHelpers.CreateSetter(PropertyInfo); 33 | 34 | [NotNull] 35 | private const string ValueToSet = "Updated benchmark string"; 36 | 37 | // Benchmark methods 38 | [Benchmark(Baseline = true)] 39 | public void SetDirect_Property() 40 | { 41 | BenchmarkObject.BenchmarkProperty = ValueToSet; 42 | } 43 | 44 | [Benchmark] 45 | public void SetDelegate_Property() 46 | { 47 | SetterDelegate(BenchmarkObject, ValueToSet); 48 | } 49 | 50 | [Benchmark] 51 | public void SetDynamicDelegate_Property() 52 | { 53 | DynamicSetterDelegate.DynamicInvoke(BenchmarkObject, ValueToSet); 54 | } 55 | 56 | [Benchmark] 57 | public void SetPropertyInfo_Property() 58 | { 59 | Type benchmarkType = BenchmarkObject.GetType(); 60 | PropertyInfo benchmarkProperty = benchmarkType.GetProperty(BenchmarkObjectPropertyName); 61 | // ReSharper disable once PossibleNullReferenceException 62 | benchmarkProperty.SetValue(BenchmarkObject, ValueToSet); 63 | } 64 | 65 | [Benchmark] 66 | public void SetPropertyInfoCache_Property() 67 | { 68 | PropertyInfo.SetValue(BenchmarkObject, ValueToSet); 69 | } 70 | 71 | [Benchmark] 72 | public void SetSigilEmit_Property() 73 | { 74 | SigilEmitSetter(BenchmarkObject, ValueToSet); 75 | } 76 | 77 | [Benchmark] 78 | public void SetExpression_Property() 79 | { 80 | ExpressionSetter(BenchmarkObject, ValueToSet); 81 | } 82 | 83 | [Benchmark] 84 | public void SetFastMember_Property() 85 | { 86 | TypeAccessor[BenchmarkObject, BenchmarkObjectPropertyName] = ValueToSet; 87 | } 88 | 89 | [Benchmark] 90 | public void SetImmediateProperty_Property() 91 | { 92 | ImmediateProperty.SetValue(BenchmarkObject, ValueToSet); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Benchmarks/PropertySetterOverObjectsBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Linq; 3 | using System.Reflection; 4 | using BenchmarkDotNet.Attributes; 5 | using Fasterflect; 6 | using FlashReflection; 7 | using JetBrains.Annotations; 8 | 9 | namespace ImmediateReflection.Benchmark 10 | { 11 | /// 12 | /// Property setter over multiple objects benchmark class. 13 | /// 14 | public class PropertySetterOverObjectsBenchmark : ObjectsBenchmarkBase 15 | { 16 | // Benchmark methods 17 | [Benchmark(Baseline = true)] 18 | public void Reflection_PropertySet_BenchmarkObject() 19 | { 20 | foreach (object obj in BenchmarkObjects) 21 | { 22 | SetPropertyReflection(obj); 23 | } 24 | } 25 | 26 | [Benchmark] 27 | public void ReflectionCache_PropertySet_BenchmarkObject() 28 | { 29 | foreach (object obj in BenchmarkObjects) 30 | { 31 | SetPropertyReflectionCache(obj); 32 | } 33 | } 34 | 35 | [Benchmark] 36 | public void HyperDescriptor_PropertySet_BenchmarkObject() 37 | { 38 | foreach (object obj in BenchmarkObjects) 39 | { 40 | SetPropertyHyperDescriptor(obj); 41 | } 42 | } 43 | 44 | [Benchmark] 45 | public void FastMember_PropertySet_BenchmarkObject() 46 | { 47 | foreach (object obj in BenchmarkObjects) 48 | { 49 | SetPropertyFastMember(obj); 50 | } 51 | } 52 | 53 | [Benchmark] 54 | public void FlashReflection_PropertySet_BenchmarkObject() 55 | { 56 | foreach (object obj in BenchmarkObjects) 57 | { 58 | SetPropertyFlashReflection(obj); 59 | } 60 | } 61 | 62 | [Benchmark] 63 | public void ImmediateReflection_PropertySet_BenchmarkObject() 64 | { 65 | foreach (object obj in BenchmarkObjects) 66 | { 67 | SetPropertyImmediateReflection(obj); 68 | } 69 | } 70 | 71 | [Benchmark] 72 | public void WithFasterflect_PropertySet_BenchmarkObject() 73 | { 74 | foreach (object obj in BenchmarkObjects) 75 | { 76 | SetPropertyFasterflect(obj); 77 | } 78 | } 79 | 80 | [Benchmark] 81 | public void Reflection_PropertySet_Mixed_BenchmarkObject() 82 | { 83 | foreach (object obj in BenchmarkMixedObjects) 84 | { 85 | SetPropertyReflection(obj); 86 | } 87 | } 88 | 89 | [Benchmark] 90 | public void ReflectionCache_PropertySet_Mixed_BenchmarkObject() 91 | { 92 | foreach (object obj in BenchmarkMixedObjects) 93 | { 94 | SetPropertyReflectionCache(obj); 95 | } 96 | } 97 | 98 | [Benchmark] 99 | public void HyperDescriptor_PropertySet_Mixed_BenchmarkObject() 100 | { 101 | foreach (object obj in BenchmarkMixedObjects) 102 | { 103 | SetPropertyHyperDescriptor(obj); 104 | } 105 | } 106 | 107 | [Benchmark] 108 | public void FastMember_PropertySet_Mixed_BenchmarkObject() 109 | { 110 | foreach (object obj in BenchmarkMixedObjects) 111 | { 112 | SetPropertyFastMember(obj); 113 | } 114 | } 115 | 116 | [Benchmark] 117 | public void FlashReflection_PropertySet_Mixed_BenchmarkObject() 118 | { 119 | foreach (object obj in BenchmarkMixedObjects) 120 | { 121 | SetPropertyFlashReflection(obj); 122 | } 123 | } 124 | 125 | [Benchmark] 126 | public void ImmediateReflection_PropertySet_Mixed_BenchmarkObject() 127 | { 128 | foreach (object obj in BenchmarkMixedObjects) 129 | { 130 | SetPropertyImmediateReflection(obj); 131 | } 132 | } 133 | 134 | [Benchmark] 135 | public void Fasterflect_PropertySet_Mixed_BenchmarkObject() 136 | { 137 | foreach (object obj in BenchmarkMixedObjects) 138 | { 139 | SetPropertyFasterflect(obj); 140 | } 141 | } 142 | 143 | #region Helper methods 144 | 145 | private static readonly uint[] ValueToSet = { 2u, 3u }; 146 | 147 | public void SetPropertyReflection([NotNull] object obj) 148 | { 149 | PropertyInfo propertyInfo = obj.GetType().GetProperty(UIntArrayPropertyName); 150 | if (propertyInfo is null || propertyInfo.PropertyType != typeof(uint[])) 151 | return; 152 | 153 | propertyInfo.SetValue(obj, ValueToSet); 154 | } 155 | 156 | public void SetPropertyReflectionCache([NotNull] object obj) 157 | { 158 | if (obj.GetType() != typeof(ObjectsBenchmarkObject1)) 159 | return; 160 | 161 | UIntArrayPropertyInfo.SetValue(obj, ValueToSet); 162 | } 163 | 164 | public void SetPropertyHyperDescriptor([NotNull] object obj) 165 | { 166 | PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(obj).Find(UIntArrayPropertyName, false); 167 | propertyDescriptor?.SetValue(obj, ValueToSet); 168 | } 169 | 170 | public void SetPropertyFastMember([NotNull] object obj) 171 | { 172 | FastMember.TypeAccessor accessor = FastMember.TypeAccessor.Create(obj.GetType()); 173 | bool hasProperty = accessor.GetMembers().Any(m => m.Name == UIntArrayPropertyName); 174 | if (!hasProperty) 175 | return; 176 | 177 | accessor[obj, UIntArrayPropertyName] = ValueToSet; 178 | } 179 | 180 | public void SetPropertyFlashReflection([NotNull] object obj) 181 | { 182 | ReflectionType type = ReflectionCache.Instance.GetReflectionType(obj.GetType()); 183 | ReflectionProperty property = type.Properties[UIntArrayPropertyName]; 184 | 185 | property?.SetValue(obj, ValueToSet); 186 | } 187 | 188 | public void SetPropertyImmediateReflection([NotNull] object obj) 189 | { 190 | ImmediateType accessor = ImmediateReflection.TypeAccessor.Get(obj.GetType()); 191 | ImmediateProperty property = accessor.GetProperty(UIntArrayPropertyName); 192 | 193 | property?.SetValue(obj, ValueToSet); 194 | } 195 | 196 | public void SetPropertyFasterflect([NotNull] object obj) 197 | { 198 | obj.TrySetPropertyValue(UIntArrayPropertyName, ValueToSet); 199 | } 200 | 201 | #endregion 202 | } 203 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Helpers/ExpressionsHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Reflection; 4 | using JetBrains.Annotations; 5 | 6 | namespace ImmediateReflection.Benchmark 7 | { 8 | /// 9 | /// Helpers to create get/set with Expression framework. 10 | /// 11 | internal static class ExpressionHelpers 12 | { 13 | [Pure] 14 | [NotNull] 15 | public static Func CreateDefaultConstructor() 16 | { 17 | Expression body = Expression.New(typeof(T)); 18 | return (Func)Expression.Lambda(body).Compile(); 19 | } 20 | 21 | [Pure] 22 | [NotNull] 23 | public static Func CreateCopyConstructor() 24 | { 25 | ConstructorInfo constructor = typeof(T).GetConstructor(new[] { typeof(T) }) 26 | ?? throw new InvalidOperationException("Class must have a copy constructor."); 27 | ParameterExpression other = Expression.Parameter(typeof(T), "other"); 28 | Expression body = Expression.New(constructor, other); 29 | return (Func)Expression.Lambda(body, other).Compile(); 30 | } 31 | 32 | [Pure] 33 | [NotNull] 34 | public static Func CreateGetter([NotNull] PropertyInfo property) 35 | { 36 | if (property is null) 37 | throw new ArgumentNullException(nameof(property)); 38 | if (typeof(T) != property.DeclaringType) 39 | throw new ArgumentException("Trying to create a delegate for the wrong type."); 40 | 41 | ParameterExpression target = Expression.Parameter(property.DeclaringType, "target"); 42 | MemberExpression propertyInfo = Expression.Property(target, property); 43 | UnaryExpression convert = Expression.TypeAs(propertyInfo, typeof(object)); 44 | 45 | return (Func)Expression.Lambda(convert, target).Compile(); 46 | } 47 | 48 | [Pure] 49 | [NotNull] 50 | public static Action CreateSetter([NotNull] PropertyInfo property) 51 | { 52 | if (property is null) 53 | throw new ArgumentNullException(nameof(property)); 54 | if (typeof(T) != property.DeclaringType) 55 | throw new ArgumentException("Trying to create a delegate for the wrong type."); 56 | 57 | ParameterExpression target = Expression.Parameter(property.DeclaringType, "target"); 58 | ParameterExpression value = Expression.Parameter(typeof(object), "value"); 59 | MethodCallExpression setterCall = Expression.Call(target, property.GetSetMethod(), Expression.Convert(value, property.PropertyType)); 60 | 61 | return (Action)Expression.Lambda(setterCall, target, value).Compile(); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/ImmediateReflection.Benchmark.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net461 5 | Exe 6 | 7 | ImmediateReflection.Benchmark 8 | 9 | 1.0.0 10 | 1.0.0 11 | 1.0.0 12 | 13 | Copyright © 2018 14 | Benchmark for ImmediateReflection library. 15 | 16 | 17 | 18 | 19 | $(DefineConstants);NET461;$(AdditionalConstants) 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/AttributesBenchmarkObject.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection.Benchmark 2 | { 3 | /// 4 | /// Benchmark object for attributes. 5 | /// 6 | public class AttributesBenchmarkObject 7 | { 8 | [TestClass] 9 | [SecondTestClass] 10 | [ThirdTestClass] 11 | public int TestProperty { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/BenchmarkObject.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection.Benchmark 2 | { 3 | /// 4 | /// Benchmark object. 5 | /// 6 | public class BenchmarkObject 7 | { 8 | // ReSharper disable once InconsistentNaming 9 | public int _benchmarkField = 42; 10 | 11 | public string BenchmarkProperty { get; set; } = "Benchmark Property string"; 12 | } 13 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/BenchmarkObject2.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection.Benchmark 2 | { 3 | /// 4 | /// Benchmark object. 5 | /// 6 | internal class BenchmarkObject2 7 | { 8 | // ReSharper disable once InconsistentNaming 9 | public float _benchmarkField = 42.5f; 10 | 11 | public int BenchmarkProperty { get; set; } = 45; 12 | } 13 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/BenchmarkObject3.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection.Benchmark 2 | { 3 | /// 4 | /// Benchmark object. 5 | /// 6 | internal class BenchmarkObject3 7 | { 8 | // ReSharper disable once InconsistentNaming 9 | public string _benchmarkField = "Benchmark Field string"; 10 | 11 | public double BenchmarkProperty { get; set; } = 22.2; 12 | } 13 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/BenchmarkObject4.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection.Benchmark 2 | { 3 | /// 4 | /// Benchmark object. 5 | /// 6 | internal class BenchmarkObject4 7 | { 8 | // ReSharper disable once InconsistentNaming 9 | public uint _benchmarkField = 15u; 10 | 11 | public short BenchmarkProperty { get; set; } = 4; 12 | } 13 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/CopyableBenchmarkObject.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace ImmediateReflection.Benchmark 4 | { 5 | /// 6 | /// Copyable benchmark object. 7 | /// 8 | public class CopyableBenchmarkObject 9 | { 10 | public CopyableBenchmarkObject([NotNull] string str) 11 | { 12 | Property = str; 13 | } 14 | 15 | public CopyableBenchmarkObject([NotNull] CopyableBenchmarkObject other) 16 | { 17 | Property = other.Property; 18 | } 19 | 20 | public string Property { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/CopyableBenchmarkObject2.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace ImmediateReflection.Benchmark 4 | { 5 | /// 6 | /// Copyable benchmark object. 7 | /// 8 | public class CopyableBenchmarkObject2 9 | { 10 | public CopyableBenchmarkObject2(int value) 11 | { 12 | Property = value; 13 | } 14 | 15 | public CopyableBenchmarkObject2([NotNull] CopyableBenchmarkObject2 other) 16 | { 17 | Property = other.Property; 18 | } 19 | 20 | public int Property { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/CopyableBenchmarkObject3.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace ImmediateReflection.Benchmark 4 | { 5 | /// 6 | /// Copyable benchmark object. 7 | /// 8 | public class CopyableBenchmarkObject3 9 | { 10 | public CopyableBenchmarkObject3(double value) 11 | { 12 | Property = value; 13 | } 14 | 15 | public CopyableBenchmarkObject3([NotNull] CopyableBenchmarkObject3 other) 16 | { 17 | Property = other.Property; 18 | } 19 | 20 | public double Property { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/Objects/CopyableBenchmarkObject4.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace ImmediateReflection.Benchmark 4 | { 5 | /// 6 | /// Copyable benchmark object. 7 | /// 8 | public class CopyableBenchmarkObject4 9 | { 10 | public CopyableBenchmarkObject4(short value) 11 | { 12 | Property = value; 13 | } 14 | 15 | public CopyableBenchmarkObject4([NotNull] CopyableBenchmarkObject4 other) 16 | { 17 | Property = other.Property; 18 | } 19 | 20 | public short Property { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /benchmarks/ImmediateReflection.Benchmark/ObjectsBenchmarkBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using JetBrains.Annotations; 5 | 6 | namespace ImmediateReflection.Benchmark 7 | { 8 | /// 9 | /// Base benchmark class with object arrays. 10 | /// 11 | public abstract class ObjectsBenchmarkBase : BenchmarkBase 12 | { 13 | #region Benchmark objects 14 | 15 | protected class ObjectsBenchmarkObject1 16 | { 17 | public string StringProperty { get; set; } 18 | 19 | public uint[] UIntArray { get; set; } 20 | } 21 | 22 | protected class ObjectsBenchmarkObject2 23 | { 24 | public int IntProperty { get; set; } 25 | 26 | public long[] LongArray { get; set; } 27 | } 28 | 29 | [NotNull] 30 | protected static readonly string UIntArrayPropertyName = nameof(ObjectsBenchmarkObject1.UIntArray); 31 | 32 | [NotNull] 33 | protected static readonly PropertyInfo UIntArrayPropertyInfo = typeof(ObjectsBenchmarkObject1).GetProperty(UIntArrayPropertyName) 34 | ?? throw new InvalidOperationException("Property does not exist."); 35 | 36 | #endregion 37 | 38 | /// 39 | /// Generates instances. 40 | /// 41 | /// Number of object to generate. 42 | /// Generated objects. 43 | private static object[] GenerateBenchmarkObjects(int nbObjects) 44 | { 45 | return Enumerable 46 | .Range(1, nbObjects) 47 | .Select(i => (object)new ObjectsBenchmarkObject1 48 | { 49 | StringProperty = $"string {i}", 50 | UIntArray = new []{ 1u, 2u, 3u } 51 | }) 52 | .ToArray(); 53 | } 54 | 55 | /// 56 | /// Generates of mixed and instances. 57 | /// 58 | /// Number of object to generate. 59 | /// Generated objects. 60 | private static object[] GenerateMixedBenchmarkObjects(int nbObjects) 61 | { 62 | return Enumerable 63 | .Range(1, nbObjects) 64 | .Select( 65 | i => i % 2 == 0 66 | ? (object)new ObjectsBenchmarkObject1 67 | { 68 | StringProperty = $"string {i}", 69 | UIntArray = new[] { 1u, 2u, 3u } 70 | } 71 | : new ObjectsBenchmarkObject2 72 | { 73 | IntProperty = i, 74 | LongArray = new []{ 1L, 2L, 3L } 75 | }) 76 | .ToArray(); 77 | } 78 | 79 | private const int NbObjects = 1000; 80 | 81 | /// 82 | /// Array of objects. 83 | /// 84 | [NotNull, ItemNotNull] 85 | protected static readonly object[] BenchmarkObjects = GenerateBenchmarkObjects(NbObjects); 86 | 87 | /// 88 | /// Array of and objects. 89 | /// 90 | [NotNull, ItemNotNull] 91 | protected static readonly object[] BenchmarkMixedObjects = GenerateMixedBenchmarkObjects(NbObjects); 92 | } 93 | } -------------------------------------------------------------------------------- /build/BuildSetup.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | 6 | -------------------------------------------------------------------------------- /build/releaseDoc.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Invoke git, handling its quirky stderr that isn't error 4 | 5 | .Outputs 6 | Git messages, and lastly the exit code 7 | 8 | .Example 9 | Invoke-Git push 10 | 11 | .Example 12 | Invoke-Git "add ." 13 | #> 14 | function Invoke-Git 15 | { 16 | param( 17 | [Parameter(Mandatory)] 18 | [string] $Command ) 19 | 20 | try { 21 | 22 | $exit = 0 23 | $path = [System.IO.Path]::GetTempFileName() 24 | 25 | Invoke-Expression "git $Command 2> $path" 26 | $exit = $LASTEXITCODE 27 | if ( $exit -gt 0 ) 28 | { 29 | Write-Error (Get-Content $path).ToString() 30 | } 31 | else 32 | { 33 | Get-Content $path | Select-Object -First 1 34 | } 35 | $exit 36 | } 37 | catch 38 | { 39 | Write-Host "Error: $_`n$($_.ScriptStackTrace)" 40 | } 41 | finally 42 | { 43 | if ( Test-Path $path ) 44 | { 45 | Remove-Item $path 46 | } 47 | } 48 | } 49 | 50 | # Only master Release 51 | if ($env:Configuration -ne "Release") 52 | { 53 | "Documentation update ignored: Not Release build."; 54 | Return; 55 | } 56 | 57 | if ($env:APPVEYOR_REPO_BRANCH -ne "master") 58 | { 59 | "Documentation update ignored: Not master branch."; 60 | Return; 61 | } 62 | 63 | # Chocolatey DocFX 64 | cinst docfx --version $env:DocFXVersion -y 65 | 66 | git config --global core.autocrlf true 67 | git config --global core.eol lf 68 | 69 | git config --global user.email $env:GITHUB_EMAIL 70 | git config --global user.name "KeRNeLith" 71 | 72 | "Generating documentation site..." 73 | docfx ./docs/docfx.json 74 | 75 | $SOURCE_DIR=$pwd.Path 76 | $TEMP_REPO_DIR="$pwd/../ImmediateReflection-gh-pages" 77 | 78 | if (Test-Path $TEMP_REPO_DIR) 79 | { 80 | "Removing temporary documentation directory $TEMP_REPO_DIR..." 81 | rm -recurse $TEMP_REPO_DIR 82 | } 83 | 84 | mkdir $TEMP_REPO_DIR 85 | 86 | "Cloning the repository gh-pages branch." 87 | # -q is to avoid git to output thing to stderr for no reason 88 | git clone -q https://github.com/KeRNeLith/ImmediateReflection.git --branch gh-pages $TEMP_REPO_DIR 89 | 90 | "Clear local repository gh-pages directory..." 91 | cd $TEMP_REPO_DIR 92 | git rm -r * 93 | 94 | "Copying documentation into the local repository gh-pages directory..." 95 | cp -recurse $SOURCE_DIR/docs/_site/* . 96 | 97 | Invoke-Git "add -A ." 98 | 99 | "Checking if there are changes in the documentation..." 100 | if (-not [string]::IsNullOrEmpty($(git status --porcelain))) 101 | { 102 | "Pushing the new documentation to the remote gh-pages branch..." 103 | 104 | git commit -m "Update generated documentation." 105 | 106 | git remote set-url origin https://$($env:GITHUB_ACCESS_TOKEN)@github.com/KeRNeLith/ImmediateReflection.git 107 | 108 | # -q is to avoid git to output thing to stderr for no reason 109 | git push -q origin gh-pages 110 | 111 | "Documentation updated in remote gh-pages branch." 112 | } 113 | else 114 | { 115 | "Documentation update ignored: No relevant changes in the documentation." 116 | } -------------------------------------------------------------------------------- /build/serveDoc.ps1: -------------------------------------------------------------------------------- 1 | docfx docs/docfx.json --serve -------------------------------------------------------------------------------- /build/setupBuild.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Update the PackagesGeneration.props to generate all packages. 4 | #> 5 | function UpdateAllPackagesGeneration() 6 | { 7 | # Update the package generation props to enable package generation of the right package 8 | $genPackagesFilePath = "./src/PackagesGeneration.props"; 9 | $genPackagesContent = Get-Content $genPackagesFilePath; 10 | $newGenPackagesContent = $genPackagesContent -replace "false","true"; 11 | $newGenPackagesContent | Set-Content $genPackagesFilePath; 12 | } 13 | 14 | <# 15 | .Synopsis 16 | Update the BuildSetup.props to make the build a deploy build. 17 | #> 18 | function UpdateDeployBuild() 19 | { 20 | # Update the package generation props to enable package generation of the right package 21 | $genPackagesFilePath = "./build/BuildSetup.props"; 22 | $genPackagesContent = Get-Content $genPackagesFilePath; 23 | $newGenPackagesContent = $genPackagesContent -replace "false","true"; 24 | $newGenPackagesContent | Set-Content $genPackagesFilePath; 25 | } 26 | 27 | 28 | # Update .props based on git tag status & setup build version 29 | if ($env:APPVEYOR_REPO_TAG -eq "true") 30 | { 31 | UpdateDeployBuild; 32 | $env:Build_Version = "$($env:APPVEYOR_REPO_TAG_NAME.Replace('v', ''))"; 33 | $env:Build_Assembly_Version = $env:Build_Version; 34 | $env:IsFullIntegrationBuild = $false; # Run only tests on deploy builds (not coverage, etc.) 35 | } 36 | else 37 | { 38 | $env:Build_Version = "$($env:APPVEYOR_BUILD_VERSION)"; 39 | $env:Build_Assembly_Version = "$env:Build_Version" -replace "\-.*",""; 40 | $env:IsFullIntegrationBuild = "$env:APPVEYOR_PULL_REQUEST_NUMBER" -eq "" -And $env:Configuration -eq "Release"; 41 | } 42 | 43 | UpdateAllPackagesGeneration; 44 | $env:Release_Name = $env:Build_Version; 45 | 46 | "Building version: $env:Build_Version"; 47 | "Building assembly version: $env:Build_Assembly_Version"; 48 | 49 | if ($env:IsFullIntegrationBuild -eq $true) 50 | { 51 | "With full integration"; 52 | 53 | $env:PATH="C:\Program Files\Java\jdk15\bin;$($env:PATH)" 54 | $env:JAVA_HOME_11_X64='C:\Program Files\Java\jdk15' 55 | $env:JAVA_HOME='C:\Program Files\Java\jdk15' 56 | } 57 | else 58 | { 59 | "Without full integration"; 60 | } -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | -------------------------------------------------------------------------------- /docs/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | .manifest 6 | -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # API Reference 2 | 3 | Welcome to the **ImmediateReflection** library API Reference! 4 | 5 | Main entry points of the library are the [TypeAccessor](ImmediateReflection.TypeAccessor.yml) and [ObjectWrapper](ImmediateReflection.ObjectWrapper.yml) classes. 6 | 7 | These classes will give you access to the full potential of the library meaning constructor/getter/setter on a given `Type`. 8 | 9 | The library also provides helpers to create strongly typed get/set delegates via the [MemberExtensions](ImmediateReflection.MemberExtensions.yml). -------------------------------------------------------------------------------- /docs/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "src/ImmediateReflection/**.csproj" 8 | ], 9 | "exclude": [ 10 | "**/obj/**", 11 | "**/bin/**", 12 | "_site/**" 13 | ], 14 | "src": ".." 15 | } 16 | ], 17 | "dest": "api", 18 | "properties": { 19 | "TargetFramework": "net45" 20 | }, 21 | "disableGitFeatures": false, 22 | "disableDefaultFilter": false 23 | } 24 | ], 25 | "build": { 26 | "content": [ 27 | { 28 | "files": [ 29 | "api/**.yml", 30 | "api/index.md" 31 | ] 32 | }, 33 | { 34 | "files": [ 35 | "documentation/**.md", 36 | "documentation/**/toc.yml", 37 | "toc.yml", 38 | "*.md" 39 | ] 40 | }, 41 | { 42 | "files": [ 43 | "RELEASE_NOTES.md" 44 | ], 45 | "src": ".." 46 | } 47 | ], 48 | "resource": [ 49 | { 50 | "files": [ 51 | "images/**" 52 | ] 53 | } 54 | ], 55 | "overwrite": [ 56 | { 57 | "files": [ 58 | "apidoc/**.md" 59 | ], 60 | "exclude": [ 61 | "obj/**", 62 | "_site/**" 63 | ] 64 | } 65 | ], 66 | "dest": "_site", 67 | "globalMetadata": { 68 | "_appFaviconPath": "images/favicon.ico", 69 | "_appLogoPath": "images/logo.svg", 70 | "_appFooter": "ImmediateReflection" 71 | }, 72 | "globalMetadataFiles": [], 73 | "fileMetadataFiles": [], 74 | "template": [ "default", "templates/material" ], 75 | "postProcessors": [], 76 | "markdownEngineName": "markdig", 77 | "noLangKeyword": false, 78 | "keepFileLink": false, 79 | "cleanupCacheHistory": false, 80 | "disableGitFeatures": false 81 | } 82 | } -------------------------------------------------------------------------------- /docs/documentation/benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | To see how **powerful** the library is, you can consult several benchmarks that have been made to compare it to others Reflection library. 4 | 5 | Here are those benchmarks: 6 | 7 | - [Get/Set](benchmarks/get_set_benchmarks.md) 8 | - [Multiple Get/Set](benchmarks/multiple_get_set_benchmarks.md) 9 | - [Get/Set multiple objects](benchmarks/get_set_multiple_objects_benchmarks.md) 10 | - [Constructor](benchmarks/default_constructor_benchmarks.md) 11 | - [Copy Constructor](benchmarks/copy_constructor_benchmarks.md) 12 | - [Get Attributes](benchmarks/attributes_benchmarks.md) -------------------------------------------------------------------------------- /docs/documentation/benchmarks/attributes_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | ## Configuration 6 | 7 | ```ini 8 | BenchmarkDotNet=v0.11.5 9 | OS=Windows 10.0.18362 10 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 11 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 12 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 13 | ``` 14 | 15 | ## Implementation details 16 | 17 | These benchmarks have been done by making multiple get of attribute. 18 | 19 | The property cache is implemented with an array storing all attributes of a given property. 20 | 21 | The Property_ByImmediateReflection_GetAttribute benchmark by getting attributes from a standard `PropertyInfo` with ImmediateReflection helpers. 22 | 23 | ## Results 24 | 25 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 26 | |-------------------------------------------- |------------:|-----------:|------------:|------:|--------:| 27 | | Property_GetAttribute | 3,189.22 ns | 78.6381 ns | 102.2517 ns | 1.00 | 0.00 | 28 | | PropertyCache_GetAttribute | 76.40 ns | 0.6781 ns | 0.5294 ns | 0.02 | 0.00 | 29 | | FastMember_GetAttribute | 3,188.79 ns | 62.4070 ns | 66.7748 ns | 0.99 | 0.03 | 30 | | **ImmediateProperty_GetAttribute** | **75.92 ns** | **0.3393 ns** | **0.3174 ns** | **0.02** | **0.00** | 31 | | *Property_ByImmediateReflection_GetAttribute* | *111.50 ns* | *1.2293 ns* | *1.1498 ns* | *0.03* | *0.00* | 32 | 33 | --- 34 | 35 | Results demonstrate that keeping the use of **ImmediateReflection** as much as possible provide the fastest access to `Type`, `FieldInfo` and `PropertyInfo` attributes. 36 | 37 | It also shows that getting attributes from standard code is always possible but has a slightly higher cost. -------------------------------------------------------------------------------- /docs/documentation/benchmarks/copy_constructor_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | ## Configuration 6 | 7 | ```ini 8 | BenchmarkDotNet=v0.11.5 9 | OS=Windows 10.0.18362 10 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 11 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 12 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 13 | ``` 14 | 15 | ## Results 16 | 17 | ### Single constructor call 18 | 19 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 20 | |------------------------------ |-----------:|-----------:|-----------:|-------:|--------:| 21 | | Direct_CopyConstructor | 2.953 ns | 0.1308 ns | 0.2488 ns | 1.00 | 0.00 | 22 | | Activator_CopyConstructor | 566.443 ns | 11.2951 ns | 13.0075 ns | 185.85 | 19.21 | 23 | | Expression_CopyConstructor | 7.727 ns | 0.2140 ns | 0.2548 ns | 2.54 | 0.21 | 24 | | **ImmediateType_CopyConstructor** | **6.313 ns** | **0.1977 ns** | **0.4774 ns** | **2.18** | **0.27** | 25 | 26 | ### Multiple constructor calls 27 | 28 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 29 | |------------------------------ |-------------:|-----------:|-----------:|-------:|--------:| 30 | | Direct_CopyConstructor | 8.716 ns | 0.1260 ns | 0.1178 ns | 1.00 | 0.00 | 31 | | Activator_CopyConstructor | 2,255.524 ns | 18.1062 ns | 16.9366 ns | 258.83 | 4.22 | 32 | | Expression_CopyConstructor | 30.300 ns | 0.1712 ns | 0.1602 ns | 3.48 | 0.05 | 33 | | **ImmediateType_CopyConstructor** | **23.860 ns** | **0.4966 ns** | **0.4147 ns** | **2.74** | **0.05** | 34 | 35 | --- 36 | 37 | Results demonstrate that **ImmediateReflection** is really faster than using the classic `Activator.CreateInstance()` to do copy constructions. -------------------------------------------------------------------------------- /docs/documentation/benchmarks/default_constructor_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | ## Configuration 6 | 7 | ```ini 8 | BenchmarkDotNet=v0.11.5 9 | OS=Windows 10.0.18362 10 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 11 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 12 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 13 | ``` 14 | 15 | ## Results 16 | 17 | ### Single constructor call 18 | 19 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 20 | |-------------------------- |----------:|----------:|----------:|------:|--------:| 21 | | Direct_Constructor | 3.775 ns | 0.1453 ns | 0.1784 ns | 1.00 | 0.00 | 22 | | Activator_Constructor | 40.120 ns | 0.9452 ns | 1.9308 ns | 10.83 | 0.73 | 23 | | Expression_Constructor | 9.413 ns | 0.1010 ns | 0.0843 ns | 2.50 | 0.12 | 24 | | FastMember_Constructor | 5.523 ns | 0.1383 ns | 0.1294 ns | 1.47 | 0.07 | 25 | | **ImmediateType_Constructor** | **6.081 ns** | **0.1902 ns** | **5.938 ns** | **1.62** | **0.12** | 26 | 27 | ### Multiple constructor calls 28 | 29 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 30 | |-------------------------- |----------:|----------:|----------:|------:|--------:| 31 | | Direct_Constructor | 10.06 ns | 0.0308 ns | 0.0273 ns | 1.00 | 0.00 | 32 | | Activator_Constructor | 188.84 ns | 1.7316 ns | 1.5350 ns | 18.77 | 0.15 | 33 | | Expression_Constructor | 35.45 ns | 0.4622 ns | 0.4098 ns | 3.52 | 0.04 | 34 | | FastMember_Constructor | 23.54 ns | 0.4225 ns | 0.3746 ns | 2.34 | 0.04 | 35 | | ImmediateType_Constructor | **23.35 ns** | **0.3559 ns** | **0.2778 ns** | 2.32** | **0.03** | 36 | 37 | --- 38 | 39 | Results demonstrate that **ImmediateReflection** is really faster than using the classic `Activator.CreateInstance()`. 40 | Note that compared to FastMember the slight difference is explained by the fact that **ImmediateReflection** 41 | tries to keep as much as possible an API like the standard one involving further checks not done in FastMember. 42 | -------------------------------------------------------------------------------- /docs/documentation/benchmarks/get_set_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | ## Configuration 6 | 7 | ```ini 8 | BenchmarkDotNet=v0.11.5 9 | OS=Windows 10.0.18362 10 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 11 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 12 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 13 | ``` 14 | 15 | ## Implementation details 16 | 17 | The Field or Property cache implementations consider as a cache the fact of having the right `PropertyInfo` ready to use with GetValue/SetValue. 18 | 19 | ## Results 20 | 21 | ### Get a field value 22 | 23 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 24 | |------------------------ |------------:|----------:|----------:|------:|--------:| 25 | | GetDirect_Field | 0.0000 ns | 0.0000 ns | 0.0000 ns | ? | ? | 26 | | GetFieldInfo_Field | 100.6782 ns | 0.1422 ns | 0.1261 ns | ? | ? | 27 | | GetFieldInfoCache_Field | 60.4257 ns | 0.7904 ns | 0.7393 ns | ? | ? | 28 | | GetFastMember_Field | 29.9598 ns | 0.4392 ns | 0.3894 ns | ? | ? | 29 | | **GetImmediateField_Field** | **5.2535 ns** | **0.1314 ns** | **0.3018 ns** | **?** | **?** | 30 | 31 | **GetDirect_Field** is a too quick action to be benchmark, considering it as immediate! 32 | 33 | ### Set a field value 34 | 35 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 36 | |------------------------ |------------:|----------:|----------:|------:|--------:| 37 | | SetDirect_Field | 0.0051 ns | 0.0085 ns | 0.0075 ns | ? | ? | 38 | | SetFieldInfo_Field | 129.9163 ns | 0.3037 ns | 0.2371 ns | ? | ? | 39 | | SetFieldInfoCache_Field | 81.8266 ns | 0.2578 ns | 0.2153 ns | ? | ? | 40 | | SetFastMember_Field | 28.8047 ns | 0.0672 ns | 0.0524 ns | ? | ? | 41 | | **SetImmediateField_Field** | **5.2266 ns** | **0.1288 ns** | **0.1205 ns** | **?** | **?** | 42 | 43 | --- 44 | 45 | ### Get a property value 46 | 47 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 48 | |------------------------------ |------------:|----------:|----------:|---------:|--------:| 49 | | GetDirect_Property | 0.3030 ns | 0.0389 ns | 0.0363 ns | 1.00 | 0.00 | 50 | | GetDelegate_Property | 4.9874 ns | 0.0986 ns | 0.1247 ns | 16.76 | 1.97 | 51 | | GetDynamicDelegate_Property | 537.3377 ns | 8.8565 ns | 8.2843 ns | 1,796.26 | 207.81 | 52 | | GetPropertyInfo_Property | 142.9487 ns | 0.7985 ns | 0.7469 ns | 477.96 | 55.61 | 53 | | GetPropertyInfoCache_Property | 87.2921 ns | 0.9230 ns | 0.8182 ns | 288.61 | 32.69 | 54 | | GetSigilEmit_Property | 5.9783 ns | 0.1159 ns | 0.1190 ns | 19.97 | 2.35 | 55 | | GetExpression_Property | 9.7760 ns | 0.1546 ns | 0.1446 ns | 32.71 | 4.03 | 56 | | GetFastMember_Property | 29.1414 ns | 0.3692 ns | 0.3453 ns | 97.45 | 11.57 | 57 | | **GetImmediateProperty_Property** | **5.1417 ns** | **0.1690 ns** | **0.4271 ns** | **17.20** | **2.52** | 58 | 59 | **GetDirect_Property** is a too quick action to be benchmark, considering it as immediate! 60 | 61 | ### Set a property value 62 | 63 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 64 | |------------------------------ |-----------:|----------:|----------:|-------:|--------:| 65 | | SetDirect_Property | 1.165 ns | 0.0101 ns | 0.0094 ns | 1.00 | 0.00 | 66 | | SetDelegate_Property | 4.596 ns | 0.0915 ns | 0.1785 ns | 3.92 | 0.13 | 67 | | SetDynamicDelegate_Property | 571.378 ns | 6.8747 ns | 6.4306 ns | 490.65 | 6.76 | 68 | | SetPropertyInfo_Property | 198.768 ns | 1.2488 ns | 1.1681 ns | 170.69 | 2.07 | 69 | | SetPropertyInfoCache_Property | 141.481 ns | 0.8785 ns | 0.7788 ns | 121.51 | 1.46 | 70 | | SetSigilEmit_Property | 4.644 ns | 0.0911 ns | 0.1152 ns | 4.00 | 0.11 | 71 | | SetExpression_Property | 7.622 ns | 0.0195 ns | 0.0183 ns | 6.55 | 0.06 | 72 | | SetFastMember_Property | 31.451 ns | 0.1225 ns | 0.1086 ns | 27.01 | 0.22 | 73 | | **SetImmediateProperty_Property** | **4.526 ns** | **0.0966 ns** | **0.0857 ns** | **3.89** | **0.08** | 74 | 75 | --- 76 | 77 | As expected **ImmediateReflection** library provides get/set access in a very fast way, while also keeping the standard interface of .NET Reflection. -------------------------------------------------------------------------------- /docs/documentation/benchmarks/get_set_multiple_objects_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | ## Configuration 6 | 7 | ```ini 8 | BenchmarkDotNet=v0.11.5 9 | OS=Windows 10.0.18362 10 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 11 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 12 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 13 | ``` 14 | 15 | ## Implementation details 16 | 17 | Each benchmark consists in iterating over a set of objects (or mixed objects) and getting a property accessor to get or set the target property of the treated object. 18 | 19 | In the case of the set of objects, it's an array of objects containing the same object type. 20 | 21 | In the case of the set of mixed objects, it's an array of objects containing 2 types of objects with alternation between those 2 types. 22 | 23 | ## Results 24 | 25 | ### Get property value 26 | 27 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 28 | |------------------------------------------------------ |-------------:|------------:|------------:|------:|--------:| 29 | | Reflection_PropertyGet_BenchmarkObject | 161.82 us | 2.8856 us | 2.6992 us | 1.00 | 0.00 | 30 | | ReflectionCache_PropertyGet_BenchmarkObject | 87.94 us | 0.9080 us | 0.8494 us | 0.54 | 0.01 | 31 | | HyperDescriptor_PropertyGet_BenchmarkObject | 827.82 us | 2.9013 us | 2.7138 us | 5.12 | 0.09 | 32 | | FastMember_PropertyGet_BenchmarkObject | 87.99 us | 1.2164 us | 1.0783 us | 0.54 | 0.01 | 33 | | FlashReflection_PropertyGet_BenchmarkObject | 437.09 us | 4.3506 us | 4.0696 us | 2.70 | 0.05 | 34 | | **ImmediateReflection_PropertyGet_BenchmarkObject** | **74.13 us** | **1.1393 us** | **0.8895 us** | **0.46** | **0.01** | 35 | | WithFasterflect_PropertyGet_BenchmarkObject | 85.21 us | 0.5650 us | 0.5008 us | 0.53 | 0.01 | 36 | | Reflection_PropertyGet_Mixed_BenchmarkObject | 101.79 us | 1.4084 us | 1.2485 us | 0.63 | 0.01 | 37 | | ReflectionCache_PropertyGet_Mixed_BenchmarkObject | 44.76 us | 0.1915 us | 0.1698 us | 0.28 | 0.00 | 38 | | HyperDescriptor_PropertyGet_Mixed_BenchmarkObject | 766.16 us | 10.4081 us | 8.6912 us | 4.73 | 0.09 | 39 | | FastMember_PropertyGet_Mixed_BenchmarkObject | 76.63 us | 0.3050 us | 0.2704 us | 0.47 | 0.01 | 40 | | FlashReflection_PropertyGet_Mixed_BenchmarkObject | 463.26 us | 6.3032 us | 5.8961 us | 2.86 | 0.06 | 41 | | **ImmediateReflection_PropertyGet_Mixed_BenchmarkObject** | **67.88 us** | **0.6324 us** | **0.5606 us** | **0.42** | **0.01** | 42 | | Fasterflect_PropertyGet_Mixed_BenchmarkObject | 14,693.05 us | 330.8783 us | 570.7487 us | 90.35 | 4.35 | 43 | 44 | ### Set property value 45 | 46 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 47 | |------------------------------------------------------ |-------------:|-----------:|-----------:|------:|--------:| 48 | | Reflection_PropertySet_BenchmarkObject | 235.83 us | 2.4116 us | 2.0138 us | 1.00 | 0.00 | 49 | | ReflectionCache_PropertySet_BenchmarkObject | 167.53 us | 1.7663 us | 1.5657 us | 0.71 | 0.01 | 50 | | HyperDescriptor_PropertySet_BenchmarkObject | 1,054.13 us | 11.7559 us | 10.4213 us | 4.47 | 0.04 | 51 | | FastMember_PropertySet_BenchmarkObject | 93.97 us | 0.8061 us | 0.6293 us | 0.40 | 0.00 | 52 | | FlashReflection_PropertySet_BenchmarkObject | 447.69 us | 7.8387 us | 7.3324 us | 1.90 | 0.03 | 53 | | **ImmediateReflection_PropertySet_BenchmarkObject** | **78.97 us** | **0.8561 us** | **0.7149 us** | **0.33** | **0.00** | 54 | | WithFasterflect_PropertySet_BenchmarkObject | 92.46 us | 1.8772 us | 2.3740 us | 0.40 | 0.01 | 55 | | Reflection_PropertySet_Mixed_BenchmarkObject | 144.99 us | 2.3385 us | 2.0730 us | 0.61 | 0.01 | 56 | | ReflectionCache_PropertySet_Mixed_BenchmarkObject | 83.63 us | 0.4110 us | 0.3643 us | 0.35 | 0.00 | 57 | | HyperDescriptor_PropertySet_Mixed_BenchmarkObject | 953.34 us | 9.3168 us | 8.2591 us | 4.05 | 0.04 | 58 | | FastMember_PropertySet_Mixed_BenchmarkObject | 79.13 us | 0.7507 us | 0.7022 us | 0.34 | 0.00 | 59 | | FlashReflection_PropertySet_Mixed_BenchmarkObject | 464.35 us | 9.2689 us | 10.3024 us | 1.98 | 0.06 | 60 | | **ImmediateReflection_PropertySet_Mixed_BenchmarkObject** | **71.93 us** | **0.8027 us** | **0.7115 us** | **0.30** | **0.00** | 61 | | Fasterflect_PropertySet_Mixed_BenchmarkObject | 14,004.96 us | 69.2554 us | 57.8314 us | 59.39 | 0.66 | 62 | 63 | --- -------------------------------------------------------------------------------- /docs/documentation/benchmarks/multiple_get_set_benchmarks.md: -------------------------------------------------------------------------------- 1 | # Benchmarks 2 | 3 | Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). 4 | 5 | These benchmarks have been done by making multiple get or set on multiple types to avoid caching of the same operation. 6 | 7 | ## Configuration 8 | 9 | ```ini 10 | BenchmarkDotNet=v0.11.5 11 | OS=Windows 10.0.18362 12 | Processor=Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores 13 | [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 14 | DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3815.0 15 | ``` 16 | 17 | ## Implementation details 18 | 19 | The Field or Property cache implementations consider as a cache the fact of having the right `PropertyInfo` ready to use with GetValue/SetValue. 20 | 21 | ## Results 22 | 23 | ### Get a field value 24 | 25 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 26 | |------------------------ |---------:|----------:|----------:|------:|--------:| 27 | | GetDirect_Field | 530.0 ns | 11.161 ns | 24.499 ns | 1.00 | 0.00 | 28 | | GetFieldInfo_Field | 966.9 ns | 11.199 ns | 10.475 ns | 1.74 | 0.08 | 29 | | GetFieldInfoCache_Field | 788.5 ns | 6.924 ns | 5.782 ns | 1.40 | 0.05 | 30 | | GetFastMember_Field | 691.2 ns | 6.194 ns | 5.794 ns | 1.24 | 0.05 | 31 | | **GetImmediateField_Field** | **538.6 ns** | **14.479 ns** | **12.835 ns** | **0.96** | **0.05** | 32 | 33 | ### Set a field value 34 | 35 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 36 | |------------------------ |-----------:|----------:|----------:|-------:|--------:| 37 | | SetDirect_Field | 1.343 ns | 0.0212 ns | 0.0188 ns | 1.00 | 0.00 | 38 | | SetFieldInfo_Field | 508.308 ns | 4.1885 ns | 3.9179 ns | 378.54 | 7.06 | 39 | | SetFieldInfoCache_Field | 334.152 ns | 3.7199 ns | 3.4796 ns | 248.86 | 4.38 | 40 | | SetFastMember_Field | 153.589 ns | 1.2526 ns | 1.0459 ns | 114.37 | 1.59 | 41 | | **SetImmediateField_Field** | **23.006 ns** | **1.0165 ns** | **1.2101 ns** | **17.31** | **1.12** | 42 | 43 | --- 44 | 45 | ### Get a property value 46 | 47 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 48 | |------------------------------ |-----------:|----------:|----------:|------:|--------:| 49 | | GetDirect_Property | 700.8 ns | 2.185 ns | 1.824 ns | 1.00 | 0.00 | 50 | | GetDelegate_Property | 723.6 ns | 3.828 ns | 3.394 ns | 1.03 | 0.01 | 51 | | GetDynamicDelegate_Property | 3,323.6 ns | 17.185 ns | 15.234 ns | 4.74 | 0.03 | 52 | | GetPropertyInfo_Property | 1,482.8 ns | 32.301 ns | 34.561 ns | 2.12 | 0.05 | 53 | | GetPropertyInfoCache_Property | 1,210.4 ns | 9.714 ns | 9.087 ns | 1.73 | 0.01 | 54 | | GetSigilEmit_Property | 728.7 ns | 7.606 ns | 6.742 ns | 1.04 | 0.01 | 55 | | GetExpression_Property | 748.6 ns | 2.830 ns | 2.509 ns | 1.07 | 0.01 | 56 | | GetFastMember_Property | 936.6 ns | 18.140 ns | 20.163 ns | 1.34 | 0.03 | 57 | | **GetImmediateProperty_Property** | **727.7 ns** | **9.243 ns** | **7.719 ns** | **1.04** | **0.01** | 58 | 59 | Note that **ImmediateReflection** performs really well if we take into account that the only better benchmark concern implementation using strong types considered as known which is in fact not the case in the mindset of **ImmediateReflection**. 60 | Indeed **ImmediateReflection** must work with `object` in a first approach and not the real property type (see `PropertyInfo.GetValue` as reference). 61 | 62 | ### Set a property value 63 | 64 | | Method | Mean | Error | StdDev | Ratio | RatioSD | 65 | |------------------------------ |-------------:|-----------:|-----------:|---------:|--------:| 66 | | SetDirect_Property | 1.402 ns | 0.0287 ns | 0.0254 ns | 1.00 | 0.00 | 67 | | SetDelegate_Property | 10.876 ns | 0.2157 ns | 0.4051 ns | 7.73 | 0.36 | 68 | | SetDynamicDelegate_Property | 2,536.329 ns | 37.2463 ns | 34.8403 ns | 1,809.40 | 45.17 | 69 | | SetPropertyInfo_Property | 858.440 ns | 13.0924 ns | 12.2467 ns | 613.07 | 13.73 | 70 | | SetPropertyInfoCache_Property | 638.475 ns | 7.7110 ns | 6.8356 ns | 455.62 | 8.86 | 71 | | SetSigilEmit_Property | 10.987 ns | 0.2192 ns | 0.5926 ns | 7.65 | 0.31 | 72 | | SetExpression_Property | 32.915 ns | 0.1765 ns | 0.1564 ns | 23.49 | 0.45 | 73 | | SetFastMember_Property | 164.237 ns | 1.0621 ns | 0.9416 ns | 117.20 | 1.72 | 74 | | **SetImmediateProperty_Property** | **22.787 ns** | **0.5222 ns** | **0.8282 ns** | **16.70** | **0.70** | 75 | 76 | Note that **ImmediateReflection** performs really well if we take into account that the only better benchmark concern implementation using strong types considered as known which is in fact not the case in the mindset of **ImmediateReflection**. 77 | Indeed **ImmediateReflection** must work with `object` in a first approach and not the real property type (see `PropertyInfo.SetValue` as reference). 78 | 79 | 80 | --- 81 | 82 | As expected **ImmediateReflection** library provides get/set access in a very fast way, while also keeping the standard interface of .NET Reflection. -------------------------------------------------------------------------------- /docs/documentation/benchmarks/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Get/Set 2 | href: get_set_benchmarks.md 3 | - name: Multiple Get/Set 4 | href: multiple_get_set_benchmarks.md 5 | - name: Get/Set multiple objects 6 | href: get_set_multiple_objects_benchmarks.md 7 | - name: Default Constructor 8 | href: default_constructor_benchmarks.md 9 | - name: Copy Constructor 10 | href: copy_constructor_benchmarks.md 11 | - name: Get Attributes 12 | href: attributes_benchmarks.md -------------------------------------------------------------------------------- /docs/documentation/general-coding-guidelines.md: -------------------------------------------------------------------------------- 1 | # General Coding Guidelines 2 | 3 | ## Introduction 4 | 5 | The coding guidelines serve the following purposes: 6 | - They create a consistent look to the code, so that readers can focus on content, not layout. 7 | - They enable readers to understand the code more quickly by making assumptions based on previous experience. 8 | - They facilitate copying, changing, and maintaining the code. 9 | 10 | ## General Principles 11 | 12 | - The guidelines should be used as a guide, they are not absolute, and exceptions are allowed when justified. 13 | - The readability is essential: 14 | 1. Be consistent in style 15 | 2. Use empty lines and spaces appropriately 16 | 3. Use descriptive names and naming conventions at all times 17 | 4. Follow existing patterns unless there is a good reason 18 | 5. Keep methods and classes short and simple (Single Responsibility Principle (SRP)) 19 | - Consider making small commits is order to keep changes easily understandable. 20 | 21 | ## Layout Conventions 22 | 23 | Code formatted the same way everywhere makes the code easier to read. 24 | Below are prefered layout settings to be used for QuikGraph. 25 | 26 | 1. Setup code editors to use four-character indents and save tab characters as spaces. 27 | 2. Write only one statement per line. 28 | 3. Write only one declaration per line. 29 | 4. Avoid more than one empty line at a time. 30 | 5. Limit the length of a line of code to about 120-140 characters to reduce unnecessary horizontal scrolling. 31 | 32 | ## Commenting Conventions 33 | 34 | Use comments liberally to provide useful context with proper English sentences. 35 | 36 | Insert one space between the comment delimiter and the comment text, as shown in the following example: 37 | 38 | ```csharp 39 | // This is a example comment. It showcases 40 | // the way comment must be written. 41 | ``` 42 | 43 | Comments generally have a blank line before and, at the very least, after the segment of code to which the comment applies (in the example it is before the `Console.WriteLine`). 44 | 45 | ```csharp 46 | int[] scores = GetScores(); 47 | 48 | // Calculate the average 49 | int count = scores.Count; 50 | double sum = scores.Sum(); 51 | double average = sum / count; 52 | 53 | Console.WriteLine(x.Average); 54 | ``` 55 | 56 | All public API must be documented using the [standard C# comments](https://docs.microsoft.com/en-US/dotnet/csharp/language-reference/language-specification/documentation-comments), and must be written at third person. 57 | Note that public API is not limited to public members/methods but also applies to inheritable structure having protected members/methods for example. -------------------------------------------------------------------------------- /docs/documentation/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ## Reflection 4 | 5 | The library is pretty simple to use, it has wrappers of standard `Type`, `FieldInfo` and `PropertyInfo` that are respectively called `ImmediateType`, `ImmediateField` and `ImmediateProperty`. 6 | 7 | The get access to fields and properties it is like the standard way, you get access to a `Type` and then request its fields and properties. 8 | The entry point of the library is the `TypeAccessor` which allows to get an `ImmediateType`. 9 | 10 | See the [ImmediateType](tutorials/immediate-type.md) section for more details. 11 | 12 | ## Open delegates 13 | 14 | The library also provides the possibility to create strongly typed get/set "open" delegates. 15 | 16 | See the [Open delegates](tutorials/open-delegates.md) section for more details. -------------------------------------------------------------------------------- /docs/documentation/guidelines/toc.yml: -------------------------------------------------------------------------------- 1 | - name: C# Coding Standards 2 | href: csharp-coding-guidelines.md 3 | - name: C# Best Practices 4 | href: csharp-best-practices.md -------------------------------------------------------------------------------- /docs/documentation/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Getting started 2 | href: tutorials/toc.yml 3 | topicHref: getting-started.md 4 | - name: Benchmarks 5 | href: benchmarks/toc.yml 6 | topicHref: benchmarks.md 7 | - name: Coding Guidelines 8 | href: guidelines/toc.yml 9 | topicHref: general-coding-guidelines.md 10 | - name: Release Notes 11 | href: ~/../RELEASE_NOTES.md -------------------------------------------------------------------------------- /docs/documentation/tutorials/immediate-field.md: -------------------------------------------------------------------------------- 1 | # Getting a field 2 | 3 | ```csharp 4 | ImmediateType type = TypeAccessor.Get(); 5 | 6 | ImmediateField field = type.GetField("_fieldName"); 7 | // or 8 | ImmediateField field = type.Fields["_fieldName"]; 9 | // There is also type.GetFields() 10 | ``` 11 | 12 | When you have type wrapping a field you are able to get or set it like in a standard way. 13 | 14 | ```csharp 15 | object instance = new MySuperType(); 16 | 17 | ImmediateField field = type.GetField("_fieldName"); 18 | 19 | // Get 20 | object fieldValue = field.GetValue(instance); 21 | 22 | // Set 23 | field.SetValue(instance, "New Value"); 24 | ``` 25 | 26 | To let the user of the library access eventual missing functionalities, each wrapping type from ImmediateReflection gives an access to the equivalent standard structure. 27 | 28 | ```csharp 29 | ImmediateField field = type.GetField("_fieldName"); 30 | 31 | FieldInfo fieldInfo = field.FieldInfo; 32 | ``` -------------------------------------------------------------------------------- /docs/documentation/tutorials/immediate-member.md: -------------------------------------------------------------------------------- 1 | # ImmediateMember 2 | 3 | Both `ImmediateType`, `ImmediateField` and `ImmediateProperty` inherit from `ImmediateMember` which provide an API to check/get attributes that are applied respectively to a type, field or a property. 4 | 5 | ## Get a member 6 | 7 | An `ImmediateType` gives access to its members meaning fields and properties. 8 | 9 | Here are some examples: 10 | 11 | ```csharp 12 | ImmediateType type = TypeAccessor.Get(); 13 | 14 | IEnumerable members = type.Members; 15 | // or 16 | IEnumerable members = type.GetMembers(); 17 | 18 | // For a member 19 | ImmediateMember member = type.GetMember("MemberName"); 20 | // or 21 | ImmediateMember member = type["MemberName"]; 22 | ``` 23 | 24 | ## Get attributes 25 | 26 | All methods are accessible in their templated and not templated versions. 27 | Following some examples of accessible methods: 28 | 29 | ```csharp 30 | ImmediateType type = ...; 31 | bool hasAttribute = type.IsDefined(); 32 | 33 | ImmediateField field = ...; 34 | MyAttribute attribute = field.GetAttribute(inherit: true); 35 | 36 | ImmediateProperty property = ...; 37 | IEnumerable attributes = property.GetAttributes(typeof(MyAttribute)); 38 | 39 | IEnumerable attributes = type.GetAllAttributes(inherit: true); 40 | ``` 41 | 42 | It is also possible to directly retrieve attributes of a given `MemberInfo` from the built in cache. 43 | 44 | ```csharp 45 | PropertyInfo property = ...; 46 | bool hasAttribute = property.IsDefinedImmediateAttribute(); 47 | 48 | FieldInfo field = ...; 49 | MyAttribute attribute = field.GetImmediateAttribute(); 50 | ``` -------------------------------------------------------------------------------- /docs/documentation/tutorials/immediate-property.md: -------------------------------------------------------------------------------- 1 | # Getting a property 2 | 3 | ```csharp 4 | ImmediateType type = TypeAccessor.Get(); 5 | 6 | ImmediateProperty property = type.GetProperty("PropertyName"); 7 | // or 8 | ImmediateProperty property = type.Properties["PropertyName"]; 9 | // There is also type.GetProperties() 10 | ``` 11 | 12 | When you have type wrapping a property you are able to get or set it like in a standard way. 13 | 14 | ```csharp 15 | object instance = new MySuperType(); 16 | 17 | ImmediateProperty property = type.GetProperty("PropertyName"); 18 | 19 | // Get 20 | object propertyValue = property.GetValue(instance); 21 | 22 | // Set 23 | property.SetValue(instance, "New Value"); 24 | ``` 25 | 26 | To let the user of the library access eventual missing functionalities, each wrapping type from ImmediateReflection gives an access to the equivalent standard structure. 27 | 28 | ```csharp 29 | ImmediateProperty property = type.GetProperty("PropertyName"); 30 | 31 | PropertyInfo propertyInfo = property.PropertyInfo; 32 | ``` -------------------------------------------------------------------------------- /docs/documentation/tutorials/immediate-type.md: -------------------------------------------------------------------------------- 1 | # ImmediateType and TypeAccessor 2 | 3 | ## Getting a type 4 | 5 | The entry point of the library is the `TypeAccessor`. 6 | 7 | See following examples: 8 | 9 | ```csharp 10 | ImmediateType type = TypeAccessor.Get(typeof(MySuperType)); 11 | 12 | // or 13 | 14 | ImmediateType type = TypeAccessor.Get(); 15 | ``` 16 | 17 | Note that there are other access methods that allow to get an `ImmediateType` with non public member or by specifying `BindingFlags`. 18 | 19 | ```csharp 20 | ImmediateType type = TypeAccessor.Get(includeNonPublicMembers: true); 21 | 22 | // or 23 | 24 | // Flags allow to get a type with member that fulfill requested flags 25 | ImmediateType type = TypeAccessor.Get(BindingFlags.Public | BindingFlags.Static); 26 | ``` 27 | 28 | Note: there is a built-in cache behind the `TypeAccessor`. 29 | 30 | ## Instantiate a type 31 | 32 | The `ImmediateType` allows to instantiate types via their default constructor if available. This feature is faster than making a traditional call to `Activator.CreateInstance(Type)`. 33 | 34 | Here is a quick example: 35 | 36 | ```csharp 37 | ImmediateType type = TypeAccessor.Get(); 38 | 39 | // Create a new instance of MySuperType 40 | object newInstance = type.New(); 41 | 42 | // You can also use the version that not throws in case of failure 43 | bool succeed = type.TryNew(out object instance, out Exception _); 44 | ``` 45 | ## Copy an instance 46 | 47 | The `ImmediateType` allows to create a copy of a given instance via a copy constructor if available. This feature is faster than making a traditional call to `Activator.CreateInstance(Type, Instance)`. 48 | 49 | Here is a quick example: 50 | 51 | ```csharp 52 | ImmediateType type = TypeAccessor.Get(); 53 | 54 | MySuperType instance = new MySuperType 55 | { 56 | TestProperty = 12 57 | }; 58 | 59 | // Create a copy instance of MySuperType 60 | object newInstance = type.Copy(instance); 61 | 62 | // You can also use the version that not throws in case of failure 63 | bool succeed = type.TryCopy(instance, out object newInstance, out Exception _); 64 | ``` 65 | 66 | Note also that a more easy way of using copy is available as extension directly when manipulating an instance. 67 | 68 | ```csharp 69 | MySuperType instance = new MySuperType 70 | { 71 | TestProperty = 12 72 | }; 73 | 74 | // Create a copy instance of MySuperType 75 | MySuperType newInstance = instance.Copy(); 76 | ``` 77 | 78 | Obviously in such situation you would have directly called the copy constructor of `MySuperType`, but we have to keep in mind that it is designed to be use when the instance we manipulate has not been created in such explicit way. 79 | -------------------------------------------------------------------------------- /docs/documentation/tutorials/object-wrapper.md: -------------------------------------------------------------------------------- 1 | # Object wrapper 2 | 3 | By using `ImmediateType` API you can manipulate get/set on object via "open" methods, meaning you can specify the instance on which applying the method. 4 | 5 | ImmediateReflection also provides an `ObjectWrapper` that does the same job as `ImmediateType` but on a "closed" way. It means that get/set will be applied only on the wrapped instance. 6 | 7 | Following a quick example: 8 | 9 | ```csharp 10 | MyClass myObject = new MyClass(); 11 | 12 | ObjectWrapper wrapper = new ObjectWrapper(myObject); 13 | 14 | // Properties/Fields 15 | ImmediateField field = wrapper.GetField("_myField"); 16 | ImmediateProperty property = wrapper.GetProperty("MyProperty"); 17 | 18 | // Get 19 | object propertyValue = wrapper.GetPropertyValue("MyProperty"); 20 | 21 | // Set 22 | wrapper.SetPropertyValue("MyOtherProperty", 42); // myObject.MyOtherProperty = 42 23 | ``` 24 | 25 | Note that the wrapper gives access to the wrapped object, its `Type`, `ImmediateType` and public members. -------------------------------------------------------------------------------- /docs/documentation/tutorials/open-delegates.md: -------------------------------------------------------------------------------- 1 | # Creating typed delegate (Open delegate) 2 | 3 | ImmediateReflection provides an API like standard one for `Type`, `FieldInfo` and `PropertyInfo`, this means get/set for properties use `object` both for target and parameter/return type. 4 | 5 | But in some cases you know the type owning a property, or better the type of the property too. 6 | 7 | To answer these cases ImmediateReflection provides extensions to `PropertyInfo` that allow you to create strongly typed delegates for an even faster get/set of properties. 8 | 9 | See some of the following examples: 10 | 11 | ```csharp 12 | class MyType 13 | { 14 | int MyProperty { get; set; } 15 | 16 | string MyStringProperty { get; set; } 17 | } 18 | 19 | PropertyInfo myProperty = typeof(MyType).GetProperty(nameof(MyType.MyProperty)); 20 | GetterDelegate getter = myProperty.CreateGetter(); 21 | 22 | // Notice that this method can throw if passing invalid types 23 | // There is also a try version 24 | bool succeed = myProperty.TryCreateGetter(out GetterDelegate getter); 25 | 26 | // Then you can use this getter simply like this 27 | MyType myObject = new MyType { MyProperty = 12 }; 28 | int value = getter(myObject); // 12 29 | 30 | 31 | // Note that the same exists for setter 32 | PropertyInfo myStringProperty = typeof(MyType).GetProperty(nameof(MyType.MyStringProperty)); 33 | SetterDelegate setter = myProperty.CreateSetter(); 34 | // Or 35 | bool succeed = myProperty.TryCreateSetter(out SetterDelegate setter); 36 | 37 | // Then you can use this getter simply like this 38 | MyType myObject = new MyType { MyStringProperty = "Init" }; 39 | setter(myObject, "New value"); // Sets myObject.MyStringProperty to "New value" 40 | ``` 41 | 42 | If you only knows the owner type then you can use the alternative version of these delegate helpers that will use object for the property value. 43 | 44 | ```csharp 45 | PropertyInfo myProperty = typeof(MyType).GetProperty(nameof(MyType.MyProperty)); 46 | GetterDelegate getter = myProperty.CreateGetter(); 47 | 48 | // Notice that this method can throw if passing invalid types 49 | // There is also a try version 50 | bool succeed = myProperty.TryCreateGetter(out GetterDelegate getter); 51 | 52 | // Then you can use this getter simply like this 53 | MyType myObject = new MyType { MyProperty = 12 }; 54 | object value = getter(myObject); // 12 wrapped in an object 55 | 56 | 57 | // Note that the same exists for setter 58 | PropertyInfo myStringProperty = typeof(MyType).GetProperty(nameof(MyType.MyStringProperty)); 59 | SetterDelegate setter = myProperty.CreateSetter(); 60 | // Or 61 | bool succeed = myProperty.TryCreateSetter(out SetterDelegate setter); 62 | 63 | // Then you can use this getter simply like this 64 | MyType myObject = new MyType { MyStringProperty = "Init" }; 65 | setter(myObject, "New value"); // Sets myObject.MyStringProperty to "New value" 66 | ``` 67 | 68 | You can then stores these delegate to boost your reflection get/set over properties. -------------------------------------------------------------------------------- /docs/documentation/tutorials/toc.yml: -------------------------------------------------------------------------------- 1 | - name: ImmediateType 2 | href: immediate-type.md 3 | - name: ImmediateMember 4 | href: immediate-member.md 5 | - name: ImmediateField 6 | href: immediate-field.md 7 | - name: ImmediateProperty 8 | href: immediate-property.md 9 | - name: ObjectWrapper 10 | href: object-wrapper.md 11 | - name: Open delegates 12 | href: open-delegates.md -------------------------------------------------------------------------------- /docs/images/check.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/images/cross.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeRNeLith/ImmediateReflection/206f8b97266dbb13bbb8fc630b6c404bd77fd593/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/immediate_reflection_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeRNeLith/ImmediateReflection/206f8b97266dbb13bbb8fc630b6c404bd77fd593/docs/images/immediate_reflection_logo.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # ImmediateReflection documentation 2 | 3 | ## Badges 4 | 5 | | | | 6 | | --- | --- | 7 | | **Build** | [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/KeRNeLith/ImmediateReflection?branch=master&svg=true)](https://ci.appveyor.com/project/KeRNeLith/ImmediateReflection) | 8 | | **Coverage** | Coveralls [![Coverage Status](https://coveralls.io/repos/github/KeRNeLith/ImmediateReflection/badge.svg?branch=master)](https://coveralls.io/github/KeRNeLith/ImmediateReflection?branch=master) SonarQube [![SonarCloud Coverage](https://sonarcloud.io/api/project_badges/measure?project=immediate_reflection&metric=coverage)](https://sonarcloud.io/component_measures/metric/coverage/list?id=immediate_reflection) | 9 | | **Quality** | [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=immediate_reflection&metric=alert_status)](https://sonarcloud.io/dashboard?id=immediate_reflection) | 10 | | **Nuget** | [![Nuget status](https://img.shields.io/nuget/v/immediatereflection.svg)](https://www.nuget.org/packages/ImmediateReflection) | 11 | | **License** | [![GitHub license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/KeRNeLith/ImmediateReflection/blob/master/LICENSE) | 12 | 13 | ## Introduction 14 | 15 | This is .NET library that aims to provide a **faster** usage of **C# reflection** features. 16 | Especially the usage of constructor, members accessors (get/set) and attributes. 17 | 18 | It provides these features while trying to keep an API as similar as the standard Reflection API (**Fully documented** and **ReSharper compliant**). 19 | 20 | To see how **powerful** the library is you can consult some benchmarks **[there](documentation/benchmarks.md)**. 21 | 22 | The library is highly tested to cover as much as possible real cases, because using Reflection is some kind of core code and must be reliable to build on it. 23 | 24 | You can find library sources on [GitHub](https://github.com/KeRNeLith/ImmediateReflection). 25 | 26 | ## Targets 27 | 28 | - .NET Standard 2.0+ 29 | - .NET Core 2.0+ 30 | - .NET Framework 4.0+ 31 | 32 | Supports Source Link 33 | 34 | ## Installation 35 | 36 | ImmediateReflection is available on [NuGet](https://www.nuget.org/packages/ImmediateReflection) 37 | 38 | PM> Install-Package ImmediateReflection 39 | 40 | -------------------------------------------------------------------------------- /docs/templates/material/partials/head.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Oscar Vasquez. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | 4 | 5 | 6 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} 7 | 8 | 9 | 10 | {{#_description}}{{/_description}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{#_noindex}}{{/_noindex}} 19 | {{#_enableSearch}}{{/_enableSearch}} 20 | {{#_enableNewTab}}{{/_enableNewTab}} 21 | -------------------------------------------------------------------------------- /docs/templates/material/styles/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #34393e; 3 | font-family: 'Roboto', sans-serif; 4 | line-height: 1.5; 5 | font-size: 16px; 6 | -ms-text-size-adjust: 100%; 7 | -webkit-text-size-adjust: 100%; 8 | word-wrap: break-word 9 | } 10 | 11 | /* HEADINGS */ 12 | 13 | h1 { 14 | font-weight: 600; 15 | font-size: 32px; 16 | } 17 | 18 | h2 { 19 | font-weight: 600; 20 | font-size: 24px; 21 | line-height: 1.8; 22 | } 23 | 24 | h3 { 25 | font-weight: 600; 26 | font-size: 20px; 27 | line-height: 1.8; 28 | } 29 | 30 | h5 { 31 | font-size: 14px; 32 | padding: 10px 0px; 33 | } 34 | 35 | article h1, 36 | article h2, 37 | article h3, 38 | article h4 { 39 | margin-top: 35px; 40 | margin-bottom: 15px; 41 | } 42 | 43 | article h4 { 44 | padding-bottom: 8px; 45 | border-bottom: 2px solid #ddd; 46 | } 47 | 48 | /* NAVBAR */ 49 | 50 | .navbar-brand>img { 51 | color: #fff; 52 | } 53 | 54 | .navbar { 55 | border: none; 56 | /* Both navbars use box-shadow */ 57 | -webkit-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5); 58 | -moz-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5); 59 | box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5); 60 | } 61 | 62 | .subnav { 63 | border-top: 1px solid #ddd; 64 | background-color: #fff; 65 | } 66 | 67 | .navbar-inverse { 68 | background-color: #0d47a1; 69 | z-index: 100; 70 | } 71 | 72 | .navbar-inverse .navbar-nav>li>a, 73 | .navbar-inverse .navbar-text { 74 | color: #fff; 75 | background-color: #0d47a1; 76 | border-bottom: 3px solid transparent; 77 | padding-bottom: 12px; 78 | } 79 | 80 | .navbar-inverse .navbar-nav>li>a:focus, 81 | .navbar-inverse .navbar-nav>li>a:hover { 82 | color: #fff; 83 | background-color: #0d47a1; 84 | border-bottom: 3px solid white; 85 | } 86 | 87 | .navbar-inverse .navbar-nav>.active>a, 88 | .navbar-inverse .navbar-nav>.active>a:focus, 89 | .navbar-inverse .navbar-nav>.active>a:hover { 90 | color: #fff; 91 | background-color: #0d47a1; 92 | border-bottom: 3px solid white; 93 | } 94 | 95 | .navbar-form .form-control { 96 | border: none; 97 | border-radius: 20px; 98 | } 99 | 100 | /* SIDEBAR */ 101 | 102 | .toc .level1>li { 103 | font-weight: 400; 104 | } 105 | 106 | .toc .nav>li>a { 107 | color: #34393e; 108 | } 109 | 110 | .sidefilter { 111 | background-color: #fff; 112 | border-left: none; 113 | border-right: none; 114 | } 115 | 116 | .sidefilter { 117 | background-color: #fff; 118 | border-left: none; 119 | border-right: none; 120 | } 121 | 122 | .toc-filter { 123 | padding: 10px; 124 | margin: 0; 125 | } 126 | 127 | .toc-filter>input { 128 | border: 2px solid #ddd; 129 | border-radius: 20px; 130 | } 131 | 132 | .toc-filter>.filter-icon { 133 | display: none; 134 | } 135 | 136 | .sidetoc>.toc { 137 | background-color: #fff; 138 | overflow-x: hidden; 139 | } 140 | 141 | .sidetoc { 142 | background-color: #fff; 143 | border: none; 144 | } 145 | 146 | /* ALERTS */ 147 | 148 | .alert { 149 | padding: 0px 0px 5px 0px; 150 | color: inherit; 151 | background-color: inherit; 152 | border: none; 153 | box-shadow: 0px 2px 2px 0px rgba(100, 100, 100, 0.4); 154 | } 155 | 156 | .alert>p { 157 | margin-bottom: 0; 158 | padding: 5px 10px; 159 | } 160 | 161 | .alert>ul { 162 | margin-bottom: 0; 163 | padding: 5px 40px; 164 | } 165 | 166 | .alert>h5 { 167 | padding: 10px 15px; 168 | margin-top: 0; 169 | text-transform: uppercase; 170 | font-weight: bold; 171 | border-radius: 4px 4px 0 0; 172 | } 173 | 174 | .alert-info>h5 { 175 | color: #1976d2; 176 | border-bottom: 4px solid #1976d2; 177 | background-color: #e3f2fd; 178 | } 179 | 180 | .alert-warning>h5 { 181 | color: #f57f17; 182 | border-bottom: 4px solid #f57f17; 183 | background-color: #fff3e0; 184 | } 185 | 186 | .alert-danger>h5 { 187 | color: #d32f2f; 188 | border-bottom: 4px solid #d32f2f; 189 | background-color: #ffebee; 190 | } 191 | 192 | /* CODE HIGHLIGHT */ 193 | pre { 194 | padding: 9.5px; 195 | margin: 0 0 10px; 196 | font-size: 13px; 197 | word-break: break-all; 198 | word-wrap: break-word; 199 | background-color: #fffaef; 200 | border-radius: 4px; 201 | box-shadow: 0px 1px 4px 1px rgba(100, 100, 100, 0.4); 202 | } -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Documentation 2 | href: documentation/ 3 | - name: API Reference 4 | href: api/ 5 | homepage: api/index.md 6 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | 8 | immediate_reflection_logo.png 9 | https://raw.githubusercontent.com/KeRNeLith/ImmediateReflection/master/docs/images/immediate_reflection_logo.png 10 | 11 | 12 | true 13 | snupkg 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/ImmediateReflection.CommonInternals/ImmediateReflection.CommonInternals.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | ce984360-54f0-406f-b8a9-e75897daed3b 7 | 8 | 9 | ImmediateReflection.CommonInternals 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/ImmediateReflection.CommonInternals/ImmediateReflection.CommonInternals.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ce984360-54f0-406f-b8a9-e75897daed3b 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/ImmediateReflection.CommonInternals/Signing/PublicKey.cs: -------------------------------------------------------------------------------- 1 | namespace ImmediateReflection 2 | { 3 | internal static class PublicKey 4 | { 5 | public const string Key = 6 | #if DEPLOY_BUILD 7 | ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100d9e0d07dfc4094926edfbffcdd039f014c8a75807633ee2c38987496d29879ea7abe134d365297ce9b2cebc853502fea34c803f753eec80cea0290670aada63070feb9e094583a83c57604613f2d1142fa51011f4727c95ace3ad7f386e19a0baa2f3789187589f7dce62d3bbd7a568640164eb39b2cfee8f50ef007cbeb21c7"; 8 | #else 9 | ""; 10 | #endif 11 | } 12 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Cache/CachesHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Reflection; 4 | using JetBrains.Annotations; 5 | 6 | namespace ImmediateReflection 7 | { 8 | /// 9 | /// Cache storing all ready to use Immediate Reflection data. 10 | /// 11 | /// This is a singleton implementation. 12 | internal sealed class CachesHandler 13 | { 14 | #region Singleton management 15 | 16 | private CachesHandler() 17 | { 18 | } 19 | 20 | /// 21 | /// Gets the cache instance. 22 | /// 23 | public static CachesHandler Instance { get; } = InstanceHandler.InternalInstance; 24 | 25 | private static class InstanceHandler 26 | { 27 | // Explicit static constructor to tell C# compiler 28 | // not to mark type as beforefieldinit 29 | static InstanceHandler() 30 | { 31 | } 32 | 33 | internal static readonly CachesHandler InternalInstance = new CachesHandler(); 34 | } 35 | 36 | #endregion 37 | 38 | #region ImmediateType cache 39 | 40 | private struct TypeCacheKey : IEquatable 41 | { 42 | [NotNull] 43 | private readonly Type _type; 44 | 45 | private readonly BindingFlags _flags; 46 | 47 | public TypeCacheKey([NotNull] Type type, BindingFlags flags) 48 | { 49 | Debug.Assert(type != null); 50 | 51 | _type = type; 52 | _flags = flags; 53 | } 54 | 55 | /// 56 | public override bool Equals(object obj) 57 | { 58 | if (obj is null) 59 | return false; 60 | return obj is TypeCacheKey other && Equals(other); 61 | } 62 | 63 | /// 64 | public bool Equals(TypeCacheKey other) 65 | { 66 | return _type == other._type && _flags == other._flags; 67 | } 68 | 69 | /// 70 | public override int GetHashCode() 71 | { 72 | return (_type.GetHashCode() * 397) ^ (int)_flags; 73 | } 74 | } 75 | 76 | [NotNull] 77 | private volatile MemoryCache _cachedTypes = new MemoryCache(); 78 | 79 | [NotNull] 80 | [ContractAnnotation("type:null => halt")] 81 | public ImmediateType GetImmediateType([NotNull] Type type, BindingFlags flags) 82 | { 83 | Debug.Assert(type != null); 84 | 85 | return _cachedTypes.GetOrCreate( 86 | new TypeCacheKey(type, flags), 87 | () => new ImmediateType(type, flags)); 88 | } 89 | 90 | #endregion 91 | 92 | #region Attributes cache 93 | 94 | [NotNull] 95 | private volatile MemoryCache _cachedAttributes = new MemoryCache(); 96 | 97 | [NotNull] 98 | [ContractAnnotation("member:null => halt")] 99 | public AttributesCache GetAttributesCache([NotNull] MemberInfo member) 100 | { 101 | Debug.Assert(member != null); 102 | 103 | return _cachedAttributes.GetOrCreate(member, () => new AttributesCache(member)); 104 | } 105 | 106 | #endregion 107 | 108 | #region Default constructor cache 109 | 110 | [NotNull] 111 | private volatile MemoryCache> _cachedDefaultConstructors = 112 | new MemoryCache>(); 113 | 114 | [NotNull] 115 | [ContractAnnotation("type:null => halt")] 116 | public ConstructorData GetDefaultConstructor([NotNull] Type type) 117 | { 118 | Debug.Assert(type != null); 119 | 120 | return _cachedDefaultConstructors.GetOrCreate(type, () => 121 | { 122 | DefaultConstructorDelegate ctor = DelegatesFactory.CreateDefaultConstructor(type, out bool hasConstructor); 123 | return new ConstructorData(ctor, hasConstructor); 124 | }); 125 | } 126 | 127 | #endregion 128 | 129 | #region Copy constructor cache 130 | 131 | [NotNull] 132 | private volatile MemoryCache> _cachedCopyConstructors = 133 | new MemoryCache>(); 134 | 135 | [NotNull] 136 | [ContractAnnotation("type:null => halt")] 137 | public ConstructorData GetCopyConstructor([NotNull] Type type) 138 | { 139 | Debug.Assert(type != null); 140 | 141 | return _cachedCopyConstructors.GetOrCreate(type, () => 142 | { 143 | CopyConstructorDelegate ctor = DelegatesFactory.CreateCopyConstructor(type, out bool hasConstructor); 144 | return new ConstructorData(ctor, hasConstructor); 145 | }); 146 | } 147 | 148 | #endregion 149 | 150 | #region Field cache 151 | 152 | [NotNull] 153 | private volatile MemoryCache _cachedFields = new MemoryCache(); 154 | 155 | [NotNull] 156 | [ContractAnnotation("field:null => halt")] 157 | public ImmediateField GetField([NotNull] FieldInfo field) 158 | { 159 | Debug.Assert(field != null); 160 | 161 | return _cachedFields.GetOrCreate(field, () => new ImmediateField(field)); 162 | } 163 | 164 | #endregion 165 | 166 | #region Property cache 167 | 168 | [NotNull] 169 | private volatile MemoryCache _cachedProperties = new MemoryCache(); 170 | 171 | [NotNull] 172 | [ContractAnnotation("property:null => halt")] 173 | public ImmediateProperty GetProperty([NotNull] PropertyInfo property) 174 | { 175 | Debug.Assert(property != null); 176 | 177 | return _cachedProperties.GetOrCreate(property, () => new ImmediateProperty(property)); 178 | } 179 | 180 | #endregion 181 | } 182 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Cache/ConstructorData.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using JetBrains.Annotations; 3 | 4 | namespace ImmediateReflection 5 | { 6 | /// 7 | /// Data stored in a constructor cache. 8 | /// 9 | /// Constructor delegate type. 10 | internal sealed class ConstructorData 11 | { 12 | /// 13 | /// Indicates if there is a constructor. 14 | /// 15 | public bool HasConstructor { get; } 16 | 17 | /// 18 | /// Constructor delegate. 19 | /// 20 | [NotNull] 21 | public TConstructorDelegate Constructor { get; } 22 | 23 | public ConstructorData([NotNull] TConstructorDelegate constructor, bool hasConstructor) 24 | { 25 | Debug.Assert(constructor != null); 26 | 27 | HasConstructor = hasConstructor; 28 | Constructor = constructor; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Cache/MemoryCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Diagnostics; 4 | using JetBrains.Annotations; 5 | 6 | namespace ImmediateReflection 7 | { 8 | /// 9 | /// Represents a type that implements a memory cache. 10 | /// 11 | /// Cache key type. 12 | /// Cache value type. 13 | internal sealed class MemoryCache 14 | where TValue : class 15 | { 16 | [NotNull] 17 | private readonly Hashtable _cache = new Hashtable(); 18 | 19 | /// 20 | /// Gets the cached value corresponding to the given if already cached, or creates 21 | /// a new entry if not available. 22 | /// 23 | /// Cache key. 24 | /// Factory method to create the value if it does not exist. 25 | /// The value. 26 | [NotNull] 27 | [ContractAnnotation("key:null => halt;valueFactory:null => halt")] 28 | public TValue GetOrCreate([NotNull] TKey key, [NotNull, InstantHandle] Func valueFactory) 29 | { 30 | Debug.Assert(key != null); 31 | Debug.Assert(valueFactory != null); 32 | 33 | // ReSharper disable once InconsistentlySynchronizedField, Justification: HashTable is thread safe for reading 34 | var cachedValue = (TValue)_cache[key]; 35 | if (cachedValue != null) 36 | return cachedValue; 37 | 38 | lock (_cache) 39 | { 40 | // Double check (init during lock wait) 41 | cachedValue = (TValue)_cache[key]; 42 | if (cachedValue != null) 43 | return cachedValue; 44 | 45 | cachedValue = valueFactory(); 46 | _cache[key] = cachedValue; 47 | return cachedValue; 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Delegates/Delegates.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace ImmediateReflection 4 | { 5 | #region Constructors 6 | 7 | /// 8 | /// Default constructor delegate. 9 | /// 10 | /// Newly created object. 11 | [PublicAPI] 12 | [NotNull] 13 | public delegate object DefaultConstructorDelegate(); 14 | 15 | /// 16 | /// Copy constructor delegate. 17 | /// 18 | /// Object to copy. 19 | /// Newly created object. 20 | [PublicAPI] 21 | [NotNull] 22 | public delegate object CopyConstructorDelegate([CanBeNull] object other); 23 | 24 | /// 25 | /// Constructor delegate. 26 | /// 27 | /// Constructor arguments. 28 | /// Newly created object. 29 | [PublicAPI] 30 | [NotNull] 31 | public delegate object ConstructorDelegate([CanBeNull, ItemCanBeNull] params object[] arguments); 32 | 33 | #endregion 34 | 35 | #region Getters 36 | 37 | /// 38 | /// Static getter delegate. 39 | /// 40 | /// Value type. 41 | /// Got value. 42 | [PublicAPI] 43 | public delegate TValue StaticGetterDelegate(); 44 | 45 | /// 46 | /// Getter delegate. 47 | /// 48 | /// Object instance to get a value, null if static. 49 | /// Got value. 50 | [PublicAPI] 51 | public delegate object GetterDelegate([CanBeNull] object target); 52 | 53 | /// 54 | /// Template getter delegate. 55 | /// 56 | /// Owner object type. 57 | /// Object instance to get a value, null if static. 58 | /// Got value. 59 | [PublicAPI] 60 | public delegate object GetterDelegate([CanBeNull] TOwner target); 61 | 62 | /// 63 | /// Template getter delegate. 64 | /// 65 | /// Owner object type. 66 | /// Value type. 67 | /// Object instance to get a value, null if static. 68 | /// Got value. 69 | [PublicAPI] 70 | public delegate TValue GetterDelegate([CanBeNull] TOwner target); 71 | 72 | /// 73 | /// Template getter delegate (ref). 74 | /// 75 | /// Owner object type. 76 | /// Value type. 77 | /// Object instance to get a value, null if static. 78 | /// Got value. 79 | internal delegate TValue RefGetterDelegate([CanBeNull] ref TOwner target); 80 | 81 | #endregion 82 | 83 | #region Setters 84 | 85 | /// 86 | /// Static setter delegate. 87 | /// 88 | /// Value type. 89 | /// Value to set. 90 | [PublicAPI] 91 | public delegate void StaticSetterDelegate([CanBeNull] TValue value); 92 | 93 | /// 94 | /// Setter delegate. 95 | /// 96 | /// Object instance to set a value, null if static. 97 | /// Value to set. 98 | [PublicAPI] 99 | public delegate void SetterDelegate([CanBeNull] object target, [CanBeNull] object value); 100 | 101 | /// 102 | /// Template setter delegate. 103 | /// 104 | /// Owner object type. 105 | /// Object instance to set a value, null if static. 106 | /// Value to set. 107 | [PublicAPI] 108 | public delegate void SetterDelegate([CanBeNull] TOwner target, [CanBeNull] object value); 109 | 110 | /// 111 | /// Template setter delegate. 112 | /// 113 | /// Owner object type. 114 | /// Value type. 115 | /// Object instance to set a value, null if static. 116 | /// Value to set. 117 | [PublicAPI] 118 | public delegate void SetterDelegate([CanBeNull] TOwner target, [CanBeNull] TValue value); 119 | 120 | #endregion 121 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Extensions/ImmediateReflectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | #if SUPPORTS_AGGRESSIVE_INLINING 3 | using System.Runtime.CompilerServices; 4 | #endif 5 | using JetBrains.Annotations; 6 | 7 | namespace ImmediateReflection 8 | { 9 | /// 10 | /// Extensions to easily work with Immediate Reflection. 11 | /// 12 | [PublicAPI] 13 | public static class ImmediateReflectionExtensions 14 | { 15 | /// 16 | /// Gets the corresponding to this instance. 17 | /// 18 | /// Object type. 19 | /// Object instance. 20 | /// The corresponding . 21 | /// If the given is null. 22 | [PublicAPI] 23 | [NotNull] 24 | [ContractAnnotation("obj:null => halt")] 25 | #if SUPPORTS_AGGRESSIVE_INLINING 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | #endif 28 | public static ImmediateType GetImmediateType([NotNull] this T obj) 29 | { 30 | if (obj == null) 31 | throw new ArgumentNullException(nameof(obj)); 32 | return TypeAccessor.Get(obj.GetType()); 33 | } 34 | 35 | /// 36 | /// Gets the corresponding to this . 37 | /// 38 | /// A . 39 | /// The corresponding . 40 | /// If the given is null. 41 | [PublicAPI] 42 | [NotNull] 43 | [ContractAnnotation("type:null => halt")] 44 | #if SUPPORTS_AGGRESSIVE_INLINING 45 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 46 | #endif 47 | public static ImmediateType GetImmediateType([NotNull] this Type type) 48 | { 49 | return TypeAccessor.Get(type); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | 4 | namespace ImmediateReflection 5 | { 6 | /// 7 | /// Extensions to work with object instance. 8 | /// 9 | [PublicAPI] 10 | public static class ObjectExtensions 11 | { 12 | /// 13 | /// Checks if this can be copied by a copy constructor. 14 | /// 15 | /// Instance type. 16 | /// Object to check if its has a copy constructor. 17 | /// True if the can be copied, false otherwise. 18 | /// If the given is null. 19 | [PublicAPI] 20 | [ContractAnnotation("instance:null => halt")] 21 | public static bool HasCopyConstructor([NotNull] this T instance) 22 | { 23 | if (instance == null) 24 | throw new ArgumentNullException(nameof(instance)); 25 | if (instance is Type) 26 | return true; 27 | return CachesHandler.Instance.GetCopyConstructor(instance.GetType()).HasConstructor; 28 | } 29 | 30 | /// 31 | /// Creates a copy instance of this with its copy constructor. 32 | /// 33 | /// Instance type. 34 | /// Object to copy. 35 | /// A reference to the newly created object. 36 | /// If the given is null. 37 | /// 38 | /// No matching public copy constructor was found, 39 | /// or constructor exists but was not considered as copy constructor. 40 | /// 41 | [PublicAPI] 42 | [ContractAnnotation("instance:null => null;instance:notnull => notnull")] 43 | public static T Copy([CanBeNull] this T instance) 44 | { 45 | if (instance == null) 46 | return default(T); 47 | if (instance is Type) 48 | return instance; 49 | return (T)CachesHandler.Instance.GetCopyConstructor(instance.GetType()).Constructor(instance); 50 | } 51 | 52 | /// 53 | /// Tries to create a copy instance of this with its copy constructor. 54 | /// 55 | /// Instance type. 56 | /// This method will not throw if instantiation failed. 57 | /// Object to copy. 58 | /// A reference to the newly created object, otherwise null. 59 | /// Caught exception if the instantiation failed, otherwise null. 60 | /// True if the new instance was successfully created, false otherwise. 61 | /// If the given is null. 62 | [PublicAPI] 63 | [ContractAnnotation("instance:null => true, newInstance:null, exception:null;" 64 | + "instance:notnull => true, newInstance:notnull, exception:null;" 65 | + "instance:null => false, newInstance:null, exception:notnull;" 66 | + "instance:notnull => false, newInstance:null, exception:notnull")] 67 | public static bool TryCopy( 68 | [CanBeNull] this T instance, 69 | out T newInstance, 70 | out Exception exception) 71 | { 72 | try 73 | { 74 | exception = null; 75 | newInstance = Copy(instance); 76 | return true; 77 | } 78 | catch (Exception ex) 79 | { 80 | newInstance = default(T); 81 | exception = ex; 82 | return false; 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Helpers/FieldHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using System.Reflection; 5 | using JetBrains.Annotations; 6 | 7 | namespace ImmediateReflection.Utils 8 | { 9 | /// 10 | /// Helpers to work with fields. 11 | /// 12 | internal static class FieldHelpers 13 | { 14 | [NotNull] 15 | private const string BackingFieldName = "BackingField"; 16 | 17 | /// 18 | /// Checks if the given corresponds to a backing field. 19 | /// 20 | /// The . 21 | /// True if the is a backing field, false otherwise. 22 | [Pure] 23 | [ContractAnnotation("field:null => halt")] 24 | internal static bool IsBackingField([NotNull] FieldInfo field) 25 | { 26 | Debug.Assert(field != null); 27 | 28 | return field.Name.Contains(BackingFieldName); 29 | } 30 | 31 | /// 32 | /// Gets an enumerable of without backing fields. 33 | /// 34 | /// Enumerable of to filter. 35 | /// Filtered . 36 | [Pure] 37 | [NotNull, ItemNotNull] 38 | [ContractAnnotation("fields:null => halt")] 39 | internal static IEnumerable IgnoreBackingFields([NotNull, ItemNotNull] IEnumerable fields) 40 | { 41 | Debug.Assert(fields != null); 42 | 43 | return fields.Where(field => !IsBackingField(field)); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/Helpers/ReflectionHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using JetBrains.Annotations; 4 | 5 | namespace ImmediateReflection.Utils 6 | { 7 | /// 8 | /// Helpers to use C# reflection. 9 | /// 10 | internal static class ReflectionHelpers 11 | { 12 | /// 13 | /// Checks if the given parameter is a parameter using "params". 14 | /// 15 | /// A . 16 | /// True if the parameter correspond to a "params" parameter, false otherwise. 17 | [Pure] 18 | [ContractAnnotation("param:null => halt")] 19 | public static bool IsParams([NotNull] ParameterInfo param) 20 | { 21 | return param.IsDefined(typeof(ParamArrayAttribute), false); 22 | } 23 | 24 | /// 25 | /// Checks if the given is an indexed one. 26 | /// 27 | /// A . 28 | /// True if the is an indexed property, false otherwise. 29 | [Pure] 30 | [ContractAnnotation("property:null => halt")] 31 | public static bool IsIndexed([NotNull] PropertyInfo property) 32 | { 33 | return property.GetIndexParameters().Length != 0; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/ImmediateFields.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Reflection; 7 | #if SUPPORTS_AGGRESSIVE_INLINING 8 | using System.Runtime.CompilerServices; 9 | #endif 10 | using System.Runtime.Serialization; 11 | using System.Security.Permissions; 12 | using JetBrains.Annotations; 13 | 14 | namespace ImmediateReflection 15 | { 16 | /// 17 | /// Represents a collection of fields and provides access to its metadata in a faster way. 18 | /// 19 | [PublicAPI] 20 | [Serializable] 21 | public sealed class ImmediateFields 22 | : IEnumerable 23 | , IEquatable 24 | , ISerializable 25 | { 26 | [NotNull] 27 | private readonly Dictionary _fields 28 | = new Dictionary(); 29 | 30 | /// 31 | /// Constructor. 32 | /// 33 | /// Enumerable of to wrap. 34 | internal ImmediateFields([NotNull, ItemNotNull] IEnumerable fields) 35 | { 36 | Init(fields); 37 | } 38 | 39 | private void Init([NotNull, ItemNotNull] IEnumerable fields) 40 | { 41 | Debug.Assert(fields != null); 42 | 43 | foreach (FieldInfo field in fields) 44 | { 45 | Debug.Assert(field != null); 46 | 47 | _fields.Add(field.Name, CachesHandler.Instance.GetField(field)); 48 | } 49 | } 50 | 51 | /// 52 | /// Gets the corresponding to the given . 53 | /// 54 | /// Field name. 55 | /// Found , otherwise null. 56 | /// If the given is null. 57 | [PublicAPI] 58 | [CanBeNull] 59 | public ImmediateField this[[NotNull] string fieldName] => 60 | _fields.TryGetValue(fieldName, out ImmediateField field) 61 | ? field 62 | : null; 63 | 64 | /// 65 | /// Gets the corresponding to the given . 66 | /// 67 | /// Field name. 68 | /// Found , otherwise null. 69 | /// If the given is null. 70 | [PublicAPI] 71 | [Pure] 72 | [CanBeNull] 73 | [ContractAnnotation("fieldName:null => halt")] 74 | #if SUPPORTS_AGGRESSIVE_INLINING 75 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 76 | #endif 77 | public ImmediateField GetField([NotNull] string fieldName) => this[fieldName]; 78 | 79 | #region Equality / IEquatable 80 | 81 | /// 82 | public override bool Equals(object obj) 83 | { 84 | return Equals(obj as ImmediateFields); 85 | } 86 | 87 | /// 88 | public bool Equals(ImmediateFields other) 89 | { 90 | if (other is null) 91 | return false; 92 | if (ReferenceEquals(this, other)) 93 | return true; 94 | if (_fields.Count != other._fields.Count) 95 | return false; 96 | return !_fields.Except(other._fields).Any(); 97 | } 98 | 99 | /// 100 | public override int GetHashCode() 101 | { 102 | int hashCode = 0; 103 | foreach (KeyValuePair pair in _fields) 104 | { 105 | hashCode = (hashCode * 397) ^ pair.Key.GetHashCode(); 106 | hashCode = (hashCode * 397) ^ pair.Value.GetHashCode(); 107 | } 108 | 109 | return hashCode; 110 | } 111 | 112 | #endregion 113 | 114 | #region IEnumerable 115 | 116 | /// 117 | IEnumerator IEnumerable.GetEnumerator() 118 | { 119 | return GetEnumerator(); 120 | } 121 | 122 | #endregion 123 | 124 | #region IEnumerable 125 | 126 | /// 127 | public IEnumerator GetEnumerator() 128 | { 129 | return _fields.Values.GetEnumerator(); 130 | } 131 | 132 | #endregion 133 | 134 | #region ISerializable 135 | 136 | private ImmediateFields(SerializationInfo info, StreamingContext context) 137 | { 138 | Init(ExtractFields()); 139 | 140 | #region Local function 141 | 142 | IEnumerable ExtractFields() 143 | { 144 | int count = (int)info.GetValue("Count", typeof(int)); 145 | for (int i = 0; i < count; ++i) 146 | { 147 | yield return (FieldInfo)info.GetValue($"Field{i}", typeof(FieldInfo)); 148 | } 149 | } 150 | 151 | #endregion 152 | } 153 | 154 | /// 155 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 156 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 157 | { 158 | info.AddValue("Count", _fields.Count); 159 | 160 | int i = -1; 161 | foreach (FieldInfo field in _fields.Select(pair => pair.Value.FieldInfo)) 162 | { 163 | info.AddValue($"Field{++i}", field); 164 | } 165 | } 166 | 167 | #endregion 168 | 169 | /// 170 | public override string ToString() 171 | { 172 | return $"[{string.Join(", ", _fields.Values)}]"; 173 | } 174 | } 175 | } -------------------------------------------------------------------------------- /src/ImmediateReflection/ImmediateReflection.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net40;net45;netstandard2.0;netstandard2.1 5 | 6 | $(Generate_ImmediateReflection) 7 | 8 | ImmediateReflection 9 | ImmediateReflection 10 | ImmediateReflection 11 | 12 | 13 | 1.0.0 14 | 1.0.0 15 | 1.0.0 16 | 17 | Copyright © 2019 18 | .NET library that aims to provide a faster usage of C# reflection features. 19 | Especially the usage of constructors, members accessors (get/set) and attributes. 20 | 21 | It provides these features while trying to keep an API as similar as the standard Reflection API. 22 | 23 | Supported platforms: 24 | - .NET Standard 2.0+ 25 | - .NET Core 2.0+ 26 | - .NET Framework 4.0+ 27 | 28 | Supports Source Link 29 | 30 | See benchmarks here: https://kernelith.github.io/ImmediateReflection/documentation/benchmarks.html. 31 | 32 | true 33 | ImmediateReflection 34 | ➟ Release 2.0.0 35 | Updates: 36 | - Update some serialization implementations for ImmediateReflection core types. 37 | - Dynamic methods generated by ImmediateReflection always use the ImmediateReflection module. 38 | 39 | Misc: 40 | - Get rid of targets anterior to .NET Framework 4.0. 41 | - Add target .NET Standard 2.1 to simplify dependency tree when used. 42 | - Assembly is CLS compliant (Common Language Specification). 43 | C# Reflection Fast Immediate Performance Delegate Dynamic 44 | 45 | 46 | 47 | 48 | ImmediateReflection .NET 4.0 49 | $(DefineConstants);NET40;$(AdditionalConstants) 50 | 51 | 52 | ImmediateReflection .NET 4.5 53 | $(DefineConstants);NET45;SUPPORTS_AGGRESSIVE_INLINING;$(AdditionalConstants) 54 | 55 | 56 | ImmediateReflection .NET Standard 2.0 57 | $(DefineConstants);NETSTANDARD2_0;SUPPORTS_AGGRESSIVE_INLINING;$(AdditionalConstants) 58 | 59 | 60 | ImmediateReflection .NET Standard 2.1 61 | $(DefineConstants);NETSTANDARD2_1;SUPPORTS_AGGRESSIVE_INLINING;$(AdditionalConstants) 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/ImmediateReflection/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using ImmediateReflection; 4 | 5 | [assembly: CLSCompliant(true)] 6 | [assembly: InternalsVisibleTo("ImmediateReflection.Benchmark" + PublicKey.Key)] 7 | [assembly: InternalsVisibleTo("ImmediateReflection.Tests" + PublicKey.Key)] -------------------------------------------------------------------------------- /src/ImmediateReflection/TypeAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | #if SUPPORTS_AGGRESSIVE_INLINING 4 | using System.Runtime.CompilerServices; 5 | #endif 6 | using JetBrains.Annotations; 7 | 8 | namespace ImmediateReflection 9 | { 10 | /// 11 | /// Provides an access to a Reflection information via an . 12 | /// gives access to Reflection features in a faster way than standard stuff. 13 | /// 14 | [PublicAPI] 15 | public static class TypeAccessor 16 | { 17 | internal const BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; 18 | 19 | /// 20 | /// Provides an access to a Reflection information via an . 21 | /// It gives access to all public instance members. 22 | /// 23 | /// Returned is cached within the library. 24 | /// to get a corresponding . 25 | [PublicAPI] 26 | [NotNull] 27 | #if SUPPORTS_AGGRESSIVE_INLINING 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | #endif 30 | public static ImmediateType Get() 31 | { 32 | return Get(typeof(T)); 33 | } 34 | 35 | /// 36 | /// Provides an access to a Reflection information via an . 37 | /// It gives access to all public instance members. 38 | /// 39 | /// Returned is cached within the library. 40 | /// to get a corresponding . 41 | /// If the given is null. 42 | [PublicAPI] 43 | [NotNull] 44 | [ContractAnnotation("type:null => halt")] 45 | #if SUPPORTS_AGGRESSIVE_INLINING 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | #endif 48 | public static ImmediateType Get([NotNull] Type type) 49 | { 50 | return Get(type, DefaultFlags); 51 | } 52 | 53 | /// 54 | /// Provides an access to a Reflection information via an . 55 | /// If is set to true it gives access to all public and not public instance members. 56 | /// 57 | /// Returned is cached within the library. 58 | /// to get a corresponding . 59 | /// Indicates if non public members should be taken into account. 60 | [PublicAPI] 61 | [NotNull] 62 | #if SUPPORTS_AGGRESSIVE_INLINING 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | #endif 65 | public static ImmediateType Get(bool includeNonPublicMembers) 66 | { 67 | return Get(typeof(T), includeNonPublicMembers); 68 | } 69 | 70 | /// 71 | /// Provides an access to a Reflection information via an . 72 | /// If is set to true it gives access to all public and not public instance members. 73 | /// 74 | /// Returned is cached within the library. 75 | /// to get a corresponding . 76 | /// Indicates if non public members should be taken into account. 77 | /// If the given is null. 78 | [PublicAPI] 79 | [NotNull] 80 | [ContractAnnotation("type:null => halt")] 81 | #if SUPPORTS_AGGRESSIVE_INLINING 82 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 | #endif 84 | public static ImmediateType Get([NotNull] Type type, bool includeNonPublicMembers) 85 | { 86 | return !includeNonPublicMembers 87 | ? Get(type) 88 | : Get(type, DefaultFlags | BindingFlags.NonPublic); 89 | } 90 | 91 | /// 92 | /// Provides an access to a Reflection information via an . 93 | /// 94 | /// Returned is cached within the library. 95 | /// to get a corresponding . 96 | /// Flags that must be taken into account to get members. 97 | [PublicAPI] 98 | [NotNull] 99 | #if SUPPORTS_AGGRESSIVE_INLINING 100 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 101 | #endif 102 | public static ImmediateType Get(BindingFlags flags) 103 | { 104 | return Get(typeof(T), flags); 105 | } 106 | 107 | /// 108 | /// Provides an access to a Reflection information via an . 109 | /// 110 | /// Returned is cached within the library. 111 | /// to get a corresponding . 112 | /// Flags that must be taken into account to get members. 113 | /// If the given is null. 114 | [PublicAPI] 115 | [NotNull] 116 | [ContractAnnotation("type:null => halt")] 117 | public static ImmediateType Get([NotNull] Type type, BindingFlags flags) 118 | { 119 | if (type is null) 120 | throw new ArgumentNullException(nameof(type)); 121 | 122 | return CachesHandler.Instance.GetImmediateType(type, flags); 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/PackagesGeneration.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | -------------------------------------------------------------------------------- /tests/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | false 8 | 9 | 10 | 11 | 12 | latest 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/Delegates/DelegatesFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace ImmediateReflection.Tests 5 | { 6 | /// 7 | /// Tests related to . 8 | /// 9 | [TestFixture] 10 | internal class DelegatesFactoryTests : ImmediateReflectionTestsBase 11 | { 12 | [Test] 13 | public void CreatePropertyGetter_CanRead() 14 | { 15 | Assert.IsNull(DelegatesFactory.CreateGetter(PublicValueTypePublicSetPropertyPropertyInfo, PublicValueTypePublicSetPropertyPropertyInfo.GetGetMethod())); 16 | Assert.IsNotNull(DelegatesFactory.CreateGetter(PublicValueTypePublicGetSetPropertyPropertyInfo, PublicValueTypePublicGetSetPropertyPropertyInfo.GetGetMethod())); 17 | } 18 | 19 | [Test] 20 | public void CreatePropertySetter_CanWrite() 21 | { 22 | Assert.IsNull(DelegatesFactory.CreateSetter(PublicValueTypePublicGetPropertyPropertyInfo, PublicValueTypePublicGetPropertyPropertyInfo.GetSetMethod())); 23 | Assert.IsNotNull(DelegatesFactory.CreateSetter(PublicValueTypePublicGetSetPropertyPropertyInfo, PublicValueTypePublicGetSetPropertyPropertyInfo.GetSetMethod())); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/Extensions/ImmediateReflectionExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace ImmediateReflection.Tests 5 | { 6 | /// 7 | /// Tests related to . 8 | /// 9 | [TestFixture] 10 | internal class ImmediateReflectionExtensionsTests : ImmediateReflectionTestsBase 11 | { 12 | [Test] 13 | public void GetImmediateTypeFromObject() 14 | { 15 | object testObject1 = new PublicValueTypeTestClass(); 16 | ImmediateType immediateType = ImmediateReflectionExtensions.GetImmediateType(testObject1); 17 | Assert.AreEqual(typeof(PublicValueTypeTestClass), immediateType.Type); 18 | 19 | PublicValueTypeTestClass testObject2 = new PublicValueTypeTestClass(); 20 | immediateType = ImmediateReflectionExtensions.GetImmediateType(testObject2); 21 | Assert.AreEqual(typeof(PublicValueTypeTestClass), immediateType.Type); 22 | 23 | TestStruct testObject3 = new TestStruct(); 24 | immediateType = ImmediateReflectionExtensions.GetImmediateType(testObject3); 25 | Assert.AreEqual(typeof(TestStruct), immediateType.Type); 26 | 27 | int testObject4 = 12; 28 | immediateType = ImmediateReflectionExtensions.GetImmediateType(testObject4); 29 | Assert.AreEqual(typeof(int), immediateType.Type); 30 | } 31 | 32 | [Test] 33 | public void GetImmediateTypeFromObject_Throws() 34 | { 35 | object testObject = null; 36 | 37 | // ReSharper disable once ReturnValueOfPureMethodIsNotUsed 38 | // ReSharper disable once AssignNullToNotNullAttribute 39 | Assert.Throws(() => ImmediateReflectionExtensions.GetImmediateType(testObject)); 40 | } 41 | 42 | [Test] 43 | public void GetImmediateTypeFromType() 44 | { 45 | Type testType = typeof(PublicValueTypeTestClass); 46 | ImmediateType immediateType = testType.GetImmediateType(); 47 | Assert.AreEqual(typeof(PublicValueTypeTestClass), immediateType.Type); 48 | 49 | testType = typeof(object); 50 | immediateType = testType.GetImmediateType(); 51 | Assert.AreEqual(typeof(object), immediateType.Type); 52 | 53 | testType = typeof(TestStruct); 54 | immediateType = testType.GetImmediateType(); 55 | Assert.AreEqual(typeof(TestStruct), immediateType.Type); 56 | 57 | testType = typeof(int); 58 | immediateType = testType.GetImmediateType(); 59 | Assert.AreEqual(typeof(int), immediateType.Type); 60 | } 61 | 62 | [Test] 63 | public void GetImmediateTypeFromType_Throws() 64 | { 65 | Type testType = null; 66 | 67 | // ReSharper disable once ReturnValueOfPureMethodIsNotUsed 68 | // ReSharper disable once AssignNullToNotNullAttribute 69 | Assert.Throws(() => testType.GetImmediateType()); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/ImmediateFieldsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | 5 | namespace ImmediateReflection.Tests 6 | { 7 | /// 8 | /// Tests related to . 9 | /// 10 | [TestFixture] 11 | internal class ImmediateFieldsTests : ImmediateReflectionTestsBase 12 | { 13 | [Test] 14 | public void ImmediateFieldsInfo() 15 | { 16 | var immediateFields1 = new ImmediateFields(SmallObjectFieldInfos); 17 | CollectionAssert.AreEquivalent( 18 | new[] 19 | { 20 | new ImmediateField(SmallObjectTestField1FieldInfo), 21 | new ImmediateField(SmallObjectTestField2FieldInfo) 22 | }, 23 | immediateFields1); 24 | 25 | var immediateFields2 = new ImmediateFields(SecondSmallObjectFieldInfos); 26 | CollectionAssert.AreNotEquivalent(immediateFields1, immediateFields2); 27 | 28 | var immediateFields3 = new ImmediateFields(EmptyFieldInfo); 29 | CollectionAssert.AreEqual( 30 | Enumerable.Empty(), 31 | immediateFields3); 32 | } 33 | 34 | [Test] 35 | public void GetField() 36 | { 37 | var immediateFields = new ImmediateFields(SmallObjectFieldInfos); 38 | var expectedField = new ImmediateField(SmallObjectTestField1FieldInfo); 39 | Assert.AreEqual(expectedField, immediateFields[nameof(SmallObject._testField1)]); 40 | Assert.AreEqual(expectedField, immediateFields.GetField(nameof(SmallObject._testField1))); 41 | 42 | Assert.IsNull(immediateFields["NotExists"]); 43 | Assert.IsNull(immediateFields.GetField("NotExists")); 44 | 45 | // ReSharper disable InconsistentNaming 46 | // ReSharper disable AssignNullToNotNullAttribute 47 | Assert.Throws(() => { var _ = immediateFields[null]; }); 48 | Assert.Throws(() => { var _ = immediateFields.GetField(null); }); 49 | // ReSharper restore AssignNullToNotNullAttribute 50 | // ReSharper restore InconsistentNaming 51 | } 52 | 53 | #region Equals/HashCode/ToString 54 | 55 | [Test] 56 | public void ImmediateFieldsEquality() 57 | { 58 | var immediateFields1 = new ImmediateFields(SmallObjectFieldInfos); 59 | var immediateFields2 = new ImmediateFields(SmallObjectFieldInfos); 60 | Assert.IsTrue(immediateFields1.Equals(immediateFields1)); 61 | Assert.IsTrue(immediateFields1.Equals(immediateFields2)); 62 | Assert.IsTrue(immediateFields1.Equals((object)immediateFields2)); 63 | Assert.IsFalse(immediateFields1.Equals(null)); 64 | 65 | var immediateFields3 = new ImmediateFields(SecondSmallObjectFieldInfos); 66 | Assert.IsFalse(immediateFields1.Equals(immediateFields3)); 67 | Assert.IsFalse(immediateFields1.Equals((object)immediateFields3)); 68 | 69 | var immediateFields4 = new ImmediateFields(PublicNestedFieldInfos); 70 | Assert.IsFalse(immediateFields4.Equals(immediateFields1)); 71 | Assert.IsFalse(immediateFields4.Equals((object)immediateFields1)); 72 | } 73 | 74 | [Test] 75 | public void ImmediateFieldsHashCode() 76 | { 77 | var immediateFields1 = new ImmediateFields(SmallObjectFieldInfos); 78 | var immediateFields2 = new ImmediateFields(SmallObjectFieldInfos); 79 | Assert.AreEqual(immediateFields1.GetHashCode(), immediateFields2.GetHashCode()); 80 | 81 | var immediateFields3 = new ImmediateFields(SecondSmallObjectFieldInfos); 82 | Assert.AreNotEqual(immediateFields1.GetHashCode(), immediateFields3.GetHashCode()); 83 | } 84 | 85 | [Test] 86 | public void ImmediateFieldsToString() 87 | { 88 | var immediateFields1 = new ImmediateFields(SmallObjectFieldInfos); 89 | string expectedToString = $"[{string.Join(", ", SmallObjectFieldInfos.Select(p => p.ToString()).ToArray())}]"; 90 | Assert.AreEqual(expectedToString, immediateFields1.ToString()); 91 | 92 | var immediateFields2 = new ImmediateFields(EmptyFieldInfo); 93 | Assert.AreEqual("[]", immediateFields2.ToString()); 94 | } 95 | 96 | #endregion 97 | } 98 | } -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/ImmediatePropertiesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | 5 | namespace ImmediateReflection.Tests 6 | { 7 | /// 8 | /// Tests related to . 9 | /// 10 | [TestFixture] 11 | internal class ImmediatePropertiesTests : ImmediateReflectionTestsBase 12 | { 13 | [Test] 14 | public void ImmediatePropertiesInfo() 15 | { 16 | var immediateProperties1 = new ImmediateProperties(SmallObjectPropertyInfos); 17 | CollectionAssert.AreEquivalent( 18 | new[] 19 | { 20 | new ImmediateProperty(SmallObjectTestProperty1PropertyInfo), 21 | new ImmediateProperty(SmallObjectTestProperty2PropertyInfo) 22 | }, 23 | immediateProperties1); 24 | 25 | var immediateProperties2 = new ImmediateProperties(SecondSmallObjectPropertyInfos); 26 | CollectionAssert.AreNotEquivalent(immediateProperties1, immediateProperties2); 27 | 28 | var immediateProperties3 = new ImmediateProperties(EmptyPropertyInfo); 29 | CollectionAssert.AreEqual( 30 | Enumerable.Empty(), 31 | immediateProperties3); 32 | } 33 | 34 | [Test] 35 | public void ImmediatePropertiesInfoWithNew() 36 | { 37 | var immediateProperties = new ImmediateProperties(new[] { ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo, BaseClassPublicGetPropertyPropertyInfo }); 38 | CollectionAssert.AreEquivalent( 39 | new[] { new ImmediateProperty(ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo) }, 40 | immediateProperties); 41 | 42 | immediateProperties = new ImmediateProperties(new[] { BaseClassPublicGetPropertyPropertyInfo, ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo }); 43 | CollectionAssert.AreEquivalent( 44 | new[] { new ImmediateProperty(ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo) }, 45 | immediateProperties); 46 | } 47 | 48 | [Test] 49 | public void GetProperty() 50 | { 51 | var immediateProperties = new ImmediateProperties(SmallObjectPropertyInfos); 52 | var expectedProperty = new ImmediateProperty(SmallObjectTestProperty1PropertyInfo); 53 | Assert.AreEqual(expectedProperty, immediateProperties[nameof(SmallObject.TestProperty1)]); 54 | Assert.AreEqual(expectedProperty, immediateProperties.GetProperty(nameof(SmallObject.TestProperty1))); 55 | 56 | Assert.IsNull(immediateProperties["NotExists"]); 57 | Assert.IsNull(immediateProperties.GetProperty("NotExists")); 58 | 59 | // ReSharper disable InconsistentNaming 60 | // ReSharper disable AssignNullToNotNullAttribute 61 | Assert.Throws(() => { var _ = immediateProperties[null]; }); 62 | Assert.Throws(() => { var _ = immediateProperties.GetProperty(null); }); 63 | // ReSharper restore AssignNullToNotNullAttribute 64 | // ReSharper restore InconsistentNaming 65 | } 66 | 67 | [Test] 68 | public void GetPropertyWithNew() 69 | { 70 | var immediateProperties = new ImmediateProperties(new[] { ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo, BaseClassPublicGetPropertyPropertyInfo }); 71 | var expectedProperty = new ImmediateProperty(ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo); 72 | Assert.AreEqual(expectedProperty, immediateProperties[nameof(ChildTypeRedefinitionTestClass.Property)]); 73 | Assert.AreEqual(expectedProperty, immediateProperties.GetProperty(nameof(ChildTypeRedefinitionTestClass.Property))); 74 | 75 | immediateProperties = new ImmediateProperties(new[] { BaseClassPublicGetPropertyPropertyInfo, ChildTypeRedefinitionClassPublicGetPropertyPropertyInfo }); 76 | Assert.AreEqual(expectedProperty, immediateProperties[nameof(ChildTypeRedefinitionTestClass.Property)]); 77 | Assert.AreEqual(expectedProperty, immediateProperties.GetProperty(nameof(ChildTypeRedefinitionTestClass.Property))); 78 | } 79 | 80 | #region Equals/HashCode/ToString 81 | 82 | [Test] 83 | public void ImmediatePropertiesEquality() 84 | { 85 | var immediateProperties1 = new ImmediateProperties(SmallObjectPropertyInfos); 86 | var immediateProperties2 = new ImmediateProperties(SmallObjectPropertyInfos); 87 | Assert.IsTrue(immediateProperties1.Equals(immediateProperties1)); 88 | Assert.IsTrue(immediateProperties1.Equals(immediateProperties2)); 89 | Assert.IsTrue(immediateProperties1.Equals((object)immediateProperties2)); 90 | Assert.IsFalse(immediateProperties1.Equals(null)); 91 | 92 | var immediateProperties3 = new ImmediateProperties(SecondSmallObjectPropertyInfos); 93 | Assert.IsFalse(immediateProperties1.Equals(immediateProperties3)); 94 | Assert.IsFalse(immediateProperties1.Equals((object)immediateProperties3)); 95 | 96 | var immediateProperties4 = new ImmediateProperties(PublicNestedPropertyInfos); 97 | Assert.IsFalse(immediateProperties4.Equals(immediateProperties1)); 98 | Assert.IsFalse(immediateProperties4.Equals((object)immediateProperties1)); 99 | } 100 | 101 | [Test] 102 | public void ImmediatePropertiesHashCode() 103 | { 104 | var immediateProperties1 = new ImmediateProperties(SmallObjectPropertyInfos); 105 | var immediateProperties2 = new ImmediateProperties(SmallObjectPropertyInfos); 106 | Assert.AreEqual(immediateProperties1.GetHashCode(), immediateProperties2.GetHashCode()); 107 | 108 | var immediateProperties3 = new ImmediateProperties(SecondSmallObjectPropertyInfos); 109 | Assert.AreNotEqual(immediateProperties1.GetHashCode(), immediateProperties3.GetHashCode()); 110 | } 111 | 112 | [Test] 113 | public void ImmediatePropertiesToString() 114 | { 115 | var immediateProperties1 = new ImmediateProperties(SmallObjectPropertyInfos); 116 | string expectedToString = $"[{string.Join(", ", SmallObjectPropertyInfos.Select(p => p.ToString()).ToArray())}]"; 117 | Assert.AreEqual(expectedToString, immediateProperties1.ToString()); 118 | 119 | var immediateProperties2 = new ImmediateProperties(EmptyPropertyInfo); 120 | Assert.AreEqual("[]", immediateProperties2.ToString()); 121 | } 122 | 123 | #endregion 124 | } 125 | } -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/ImmediateReflection.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net40;net45;net451;net452;net46;net461;net462;net47;net471;net472;net48;netcoreapp3.1;net5.0 5 | 6 | ImmediateReflection.Tests 7 | 8 | 1.0.0 9 | 1.0.0 10 | 1.0.0 11 | 12 | Copyright © 2019 13 | Tests for ImmediateReflection library. 14 | 15 | 16 | 17 | 18 | $(DefineConstants);NET40;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 19 | 20 | 21 | $(DefineConstants);NET45;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 22 | 23 | 24 | $(DefineConstants);NET451;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 25 | 26 | 27 | $(DefineConstants);NET452;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 28 | 29 | 30 | $(DefineConstants);NET46;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 31 | 32 | 33 | $(DefineConstants);NET461;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 34 | 35 | 36 | $(DefineConstants);NET462;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 37 | 38 | 39 | $(DefineConstants);NET47;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 40 | 41 | 42 | $(DefineConstants);NET471;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 43 | 44 | 45 | $(DefineConstants);NET472;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 46 | 47 | 48 | $(DefineConstants);NET48;SUPPORTS_SERIALIZATION;$(AdditionalConstants) 49 | 50 | 51 | $(DefineConstants);NETCOREAPP3_1;$(AdditionalConstants) 52 | 53 | 54 | $(DefineConstants);NET5_0;$(AdditionalConstants) 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /tests/ImmediateReflection.Tests/TypeAccessorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using NUnit.Framework; 5 | 6 | namespace ImmediateReflection.Tests 7 | { 8 | /// 9 | /// Tests related to . 10 | /// 11 | [TestFixture] 12 | internal class TypeAccessorTests : ImmediateReflectionTestsBase 13 | { 14 | [Test] 15 | public void Get() 16 | { 17 | TypeClassifiedMembers classifiedMembers = TypeClassifiedMembers.GetForPublicValueTypeTestObject(); 18 | 19 | ImmediateType immediateType = TypeAccessor.Get(); 20 | CheckPublicInstanceMembers(immediateType); 21 | 22 | immediateType = TypeAccessor.Get(typeof(PublicValueTypeTestClass)); 23 | CheckPublicInstanceMembers(immediateType); 24 | 25 | immediateType = TypeAccessor.Get(false); 26 | CheckPublicInstanceMembers(immediateType); 27 | 28 | immediateType = TypeAccessor.Get(typeof(PublicValueTypeTestClass), false); 29 | CheckPublicInstanceMembers(immediateType); 30 | 31 | #region Local function 32 | 33 | void CheckPublicInstanceMembers(ImmediateType type) 34 | { 35 | Assert.IsNotNull(type); 36 | Assert.AreEqual(typeof(PublicValueTypeTestClass), type.Type); 37 | // Public instance members 38 | CollectionAssert.AreEqual( 39 | classifiedMembers.PublicInstanceFields.Concat(classifiedMembers.StaticFields).Concat(classifiedMembers.ConstFields), 40 | type.Fields.Select(field => field.FieldInfo)); 41 | CollectionAssert.AreEquivalent( 42 | classifiedMembers.PublicInstanceProperties.Concat(classifiedMembers.StaticProperties), 43 | type.Properties.Select(property => property.PropertyInfo)); 44 | } 45 | 46 | #endregion 47 | } 48 | 49 | [Test] 50 | public void GetWithNonPublic() 51 | { 52 | TypeClassifiedMembers classifiedMembers = TypeClassifiedMembers.GetForPublicValueTypeTestObject(); 53 | 54 | ImmediateType immediateType = TypeAccessor.Get(true); 55 | CheckPublicAndNonPublicInstanceMembers(immediateType); 56 | 57 | immediateType = TypeAccessor.Get(typeof(PublicValueTypeTestClass), true); 58 | CheckPublicAndNonPublicInstanceMembers(immediateType); 59 | 60 | #region Local functions 61 | 62 | void CheckPublicAndNonPublicInstanceMembers(ImmediateType type) 63 | { 64 | Assert.IsNotNull(type); 65 | Assert.AreEqual(typeof(PublicValueTypeTestClass), type.Type); 66 | // Public & Non Public instance members 67 | CollectionAssert.AreEquivalent( 68 | classifiedMembers.AllFields, 69 | immediateType.Fields.Select(field => field.FieldInfo)); 70 | CollectionAssert.AreEquivalent( 71 | classifiedMembers.PublicInstanceProperties.Concat(classifiedMembers.NonPublicInstanceProperties).Concat(classifiedMembers.StaticProperties), 72 | immediateType.Properties.Select(property => property.PropertyInfo)); 73 | } 74 | 75 | #endregion 76 | } 77 | 78 | [Test] 79 | public void GetWithFlags() 80 | { 81 | TypeClassifiedMembers classifiedMembers = TypeClassifiedMembers.GetForPublicValueTypeTestObject(); 82 | 83 | const BindingFlags flags = BindingFlags.Public | BindingFlags.Static; 84 | ImmediateType immediateType = TypeAccessor.Get(flags); 85 | CheckStaticInstanceMembers(immediateType); 86 | 87 | immediateType = TypeAccessor.Get(typeof(PublicValueTypeTestClass), flags); 88 | CheckStaticInstanceMembers(immediateType); 89 | 90 | #region Local functions 91 | 92 | void CheckStaticInstanceMembers(ImmediateType type) 93 | { 94 | Assert.IsNotNull(type); 95 | Assert.AreEqual(typeof(PublicValueTypeTestClass), type.Type); 96 | // Static members 97 | CollectionAssert.AreEqual( 98 | classifiedMembers.StaticFields.Concat(classifiedMembers.ConstFields), 99 | immediateType.Fields.Select(field => field.FieldInfo)); 100 | CollectionAssert.AreEquivalent( 101 | classifiedMembers.StaticProperties, 102 | immediateType.Properties.Select(property => property.PropertyInfo)); 103 | } 104 | 105 | #endregion 106 | } 107 | 108 | [Test] 109 | public void Get_NullType() 110 | { 111 | // ReSharper disable AssignNullToNotNullAttribute 112 | // ReSharper disable ReturnValueOfPureMethodIsNotUsed 113 | Assert.Throws(() => TypeAccessor.Get(null)); 114 | Assert.Throws(() => TypeAccessor.Get(null, false)); 115 | Assert.Throws(() => TypeAccessor.Get(null, true)); 116 | Assert.Throws(() => TypeAccessor.Get(null, BindingFlags.Public | BindingFlags.Instance)); 117 | // ReSharper disable ReturnValueOfPureMethodIsNotUsed 118 | // ReSharper restore AssignNullToNotNullAttribute 119 | } 120 | 121 | [Test] 122 | public void GetCached() 123 | { 124 | ImmediateType immediateType1 = TypeAccessor.Get(typeof(PublicValueTypeTestClass)); 125 | Assert.IsNotNull(immediateType1); 126 | 127 | ImmediateType immediateType2 = TypeAccessor.Get(); 128 | Assert.IsNotNull(immediateType2); 129 | 130 | Assert.AreSame(immediateType1, immediateType2); 131 | } 132 | } 133 | } --------------------------------------------------------------------------------