├── .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** | [](https://ci.appveyor.com/project/KeRNeLith/ImmediateReflection) |
8 | | **Coverage** | Coveralls [](https://coveralls.io/github/KeRNeLith/ImmediateReflection?branch=master) SonarQube [](https://sonarcloud.io/component_measures/metric/coverage/list?id=immediate_reflection) |
9 | | **Quality** | [](https://sonarcloud.io/dashboard?id=immediate_reflection) |
10 | | **Nuget** | [](https://www.nuget.org/packages/ImmediateReflection) |
11 | | **License** | [](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 | }
--------------------------------------------------------------------------------