Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature implementation: DynamicObject support #40

Open
daball opened this issue Nov 29, 2014 · 2 comments
Open

Feature implementation: DynamicObject support #40

daball opened this issue Nov 29, 2014 · 2 comments

Comments

@daball
Copy link

daball commented Nov 29, 2014

I've created some initial support for DynamicObject objects. It works for DynamicObject objects that have members, but not indexes (like Array, IList, etc.). For the moment, it depends on Dynamitey.

It's over here in commit 05a7da4 and 90ef52c. I'm probably going to work on it some more before I'll be completely happy with it, but it does work.

This is a feature that is going to be required for a project I'm working on. I would be interested in what sort of inputs you might have regarding this feature as the project maintainer. I would be happy to send you a Pull Request when I wrap up the work on it. And, I'll be sure to include some test cases for DynamicObject objects as well.

@jehugaleahsa
Copy link
Owner

I am a bit curious. In what situation are you using DynamicObject? I can see someone using an ExpandoObject, but I don't know in what context an actual instance of DynamicObject is getting tossed around. Is this something another library is returning to your code?

Normally, projects use a DynamicObject to provide access to an underlying dictionary items via properties. In many of the libraries I have used, you can get direct access to the dictionary (raw) representation, as well.

This is still definitely something I'd like to support at some point. I am actually debating whether it would make sense in my event handlers to expose key/variable scopes using a dynamic object, a thin DynamicObject wrapper around my Scope class.

Just curious...

@daball
Copy link
Author

daball commented Dec 20, 2014

Sorry I hadn't gotten back to you sooner. DynamicObject is an abstract type and the base object of ExpandoObject. While I am not sure what higher level object of type DynamicObject gets created when the dynamic keyword is used, it is evident that all objects created out of the dynamic keyword are some implementation of the DynamicObject type.

The DynamicObject type actually has three basic sets of operations in which it can be used. It can be used as a key-value container (such as an object with properties/attributes), via TryGetMember(), TrySetMember(), and TryDeleteMember(); as an index-value container (such as a list or an array), via TryGetIndex(), TrySetIndex(), and TryDeleteIndex(); or as a simple value container (such as a string or an integer or a boolean or any higher level object), via TryConvert(), which should try to cast the value of a type out of the DynamicObject instance.

But, alone, DynamicObject doesn't implement these. It is up to the implementer to decide on how to store and retrieve this information. However the compiler does it, I do not know. However ExpandoObject works, we can presume that it uses a Dictionary<string, object> type.

For my particular needs, I needed a DynamicObject created at run-time, not at declaration-time, and it needed to behave as any of a value, object, or array type. ExpandoObject simply does not do this. And since there is no specific implementation of DynamicObject that really does anything like this, I decided to implement my own DynamicObject type that does, and interestingly enough, called it Scope--not to be confused with your Scope type.

My end game was to be able to create a global variable Scope object, be able to manipulate it by either setting an internal value; adding members, which also get wrapped by another Scope instance; or adding indexed members, which also get wrapped by another Scope instance. So, for every variable stored at any level, it will be at a minimum stored as a value-based Scope instance. This then creates a tree of Scope objects, which at their node-level contain some value object and at their tree level either use a Dictionary or a List to store either members or indexed members, respectively.

The final purpose was to be able to take input data from any data source and dump it into a variable of type Scope and to be able to either assign that Scope to the global scope or assign it to a member of any other Scope within the global scope. So, for instance, I could import a data table Customers into a Scope instance of the indexed type, with at each indexed member a Scope of the member type, with at each member, a Scope of the value type. And when this DynamicObject gets sent to your Generator.Render() method that I have modified for supporting DynamicObject objects, then template code that looks like {{#each Customers}}{{Name}}{{#newline}}{{Address1}}{{#newline}}...{{/each}} would actually be able to retrieve data in a very systematic way. This is useful because I wanted to be able to import multiple data sources into the same object-property variable schema.

... And, it works. Hopefully you can see where I'm going with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants