Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
We have a project that requires running expressions on mostly configuration based objects (in reality they're nested dictionaries with per-member/per-dict configuration of what variables are stored inside, with type information).
These expressions may in the future be written by people with limited technical experience, so
field * 5
is easy to explain but(int)data["field"] * 5
is harder, and it gets worse from there ((int)((List<Dictionary<string,object>>)this["child"])[0].field
vschild.field
)We could use dynamic objects but that would require generating a lot of them as it's a complex hierarchical data structure, and this would lose type information, as well as performance.
Instead I've made a small interface that serves as an extension point, if it's used then on attempting to resolve member access it will first attempt to call
bool TryGetMemberAccess(Expression leftHand, string identifier, out Expression result)
.If it returns false normal code flow resumes, if true is returned result should be an Expression that represents the member access.
This can of course be anything, in the unit tests it generates a dictionary access and a cast.
Case insensitivity must be implemented by the implementer of IMemberAccessProvider if they with to use case insensitivity.